open-sponsor-widget 1.0.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rahul Vyas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README ADDED
@@ -0,0 +1,25 @@
1
+ # Open Sponsor Widget
2
+
3
+ A lightweight, reusable React widget that allows you to add a sponsorship/support section (like "Buy Me a Coffee") to your website or application.
4
+
5
+ It is designed to be simple, customizable, and easy to integrate into any React 18+ project.
6
+
7
+ ---
8
+
9
+ ## âœĻ Features
10
+
11
+ - ⚛ïļ Built for React 18+
12
+ - ðŸ“Ķ ESM + CommonJS + UMD builds
13
+ - 🧠 TypeScript support included
14
+ - ðŸŽĻ Styled with Tailwind (no global resets)
15
+ - 🌍 CDN compatible (unpkg & jsDelivr)
16
+ - ðŸŠķ Lightweight and optimized
17
+
18
+ ---
19
+
20
+ ## ðŸ“Ķ Installation
21
+
22
+ Using npm:
23
+
24
+ ```bash
25
+ npm install open-sponsor-widget
@@ -0,0 +1,2 @@
1
+ export { SponsorWidget } from "./components/SponsorWidget";
2
+ export type { SponsorWidgetProps, SponsorPlatform, SponsorLink, PreviousSponsor, ButtonVariant, SponsorTheme, SponsorLayout, FundingGoal, HeroSection, AnimationConfig } from "./types/Index";
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import { SponsorWidgetProps } from "../types/Index";
3
+ import "../styles/Style.css";
4
+ export declare const SponsorWidget: React.FC<SponsorWidgetProps>;
@@ -0,0 +1,2 @@
1
+ "use strict";var e=require("react/jsx-runtime"),r=require("react");const t={buymeacoffee:{label:"Buy Me a Coffee",color:"bg-yellow-400 hover:bg-yellow-500 text-black"},patreon:{label:"Support on Patreon",color:"bg-orange-500 hover:bg-orange-600 text-white"},opencollective:{label:"Donate via OpenCollective",color:"bg-blue-500 hover:bg-blue-600 text-white"},github:{label:"Sponsor on GitHub",color:"bg-gray-800 hover:bg-black text-white"},custom:{label:"Support Us",color:"bg-indigo-600 hover:bg-indigo-700 text-white"}};function a(e,r){const a="w-full rounded-xl px-5 py-3 font-medium transition-all duration-300 flex items-center justify-center gap-2",l=e.variant??"solid",s=t[e.platform]??t.custom,o=e.color??s.color;return"outline"===l?`${a} border border-current ${o.replace("bg-","text-")}`:"ghost"===l?`${a} bg-transparent ${o.replace("bg-","text-")}`:"gradient"===l?`${a} bg-gradient-to-r from-indigo-500 to-purple-600 text-white`:`${a} ${o}`}function l(e=0,r=1){return r?Math.min(e/r*100,100):0}exports.SponsorWidget=({title:s,description:o,hero:n,previousSponsors:i,links:c,goal:d,layout:m="default",theme:u="light",className:x="",containerClassName:g="",renderSponsor:h,renderButton:p,openInNewTab:b=!0,animation:f})=>{const j="dark"===u,v=j?"bg-gray-900 text-white":"bg-white text-gray-900",y=!1!==f?.enabled?"transition-all duration-300":"";return e.jsxs("div",{className:`max-w-3xl mx-auto rounded-2xl shadow-lg p-8 space-y-10 transition-all duration-300 ${v} ${g}`,children:[n?.image&&e.jsx("div",{className:"flex justify-center",children:e.jsx("img",{src:n.image,alt:n.imageAlt??"Sponsor Hero",className:"w-24 h-24 object-contain rounded-xl",title:n.imageAlt??"Sponsor Hero"})}),e.jsxs("div",{className:"text-center space-y-4",children:[e.jsx("h2",{className:"text-3xl font-bold",children:s}),o&&e.jsx("p",{className:"max-w-xl mx-auto "+(j?"text-gray-300":"text-gray-600"),children:o})]}),d?.enabled&&e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex justify-between text-sm font-medium",children:[e.jsxs("span",{children:["Goal: ",d.currency??"$",d.amount]}),e.jsxs("span",{children:["Raised: ",d.currency??"$",d.currentAmount??0]})]}),e.jsx("div",{className:"w-full h-3 rounded-full "+(j?"bg-gray-700":"bg-gray-200"),children:e.jsx("div",{className:"h-3 rounded-full bg-indigo-500 transition-all duration-500",style:{width:`${l(d.currentAmount,d.amount)}%`}})})]}),i&&i.length>0&&e.jsxs("div",{className:"space-y-4",children:[e.jsx("h3",{className:"text-lg font-semibold text-center",children:"💛 Previous Sponsors"}),e.jsx("div",{className:"grid gap-4 "+("compact"===m?"grid-cols-3":"grid-cols-2 md:grid-cols-4"),children:i.map((t,a)=>h?e.jsx(r.Fragment,{children:h(t)},a):e.jsxs("a",{href:t.profileUrl??"#",target:b?"_blank":"_self",rel:"noopener noreferrer",className:`flex flex-col items-center justify-center p-4 rounded-xl shadow-sm hover:shadow-md ${!1!==f?.hoverScale?"hover:scale-105":""} ${y}`,children:[t.avatar&&e.jsx("img",{src:t.avatar,alt:t.name,className:"w-12 h-12 rounded-full object-cover mb-2"}),e.jsx("span",{className:"text-sm font-medium text-center",children:t.name})]},a))})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsx("h3",{className:"text-lg font-semibold text-center",children:"🚀 Support This Project"}),e.jsx("div",{className:"space-y-3",children:c.map((l,s)=>{if(p)return e.jsx(r.Fragment,{children:p(l)},s);const o=t[l.platform]??t.custom;return e.jsxs("a",{href:l.url,target:b?"_blank":"_self",rel:"noopener noreferrer",className:`${a(l)} ${!1!==f?.hoverScale?"hover:scale-[1.02]":""} ${y}`,children:[l.icon,l.name??o.label]},s)})})]})]})};
2
+ //# sourceMappingURL=index.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/components/SponsorWidget.tsx"],"sourcesContent":["import React from \"react\";\r\nimport { SponsorWidgetProps, SponsorLink, PreviousSponsor } from \"../types/Index\";\r\nimport \"../styles/Style.css\";\r\n\r\n/* =========================================================\r\n Internal Helpers\r\n========================================================= */\r\n\r\nconst platformDefaults: Record<string, { label: string; color: string }> = {\r\n buymeacoffee: {\r\n label: \"Buy Me a Coffee\",\r\n color: \"bg-yellow-400 hover:bg-yellow-500 text-black\",\r\n },\r\n patreon: {\r\n label: \"Support on Patreon\",\r\n color: \"bg-orange-500 hover:bg-orange-600 text-white\",\r\n },\r\n opencollective: {\r\n label: \"Donate via OpenCollective\",\r\n color: \"bg-blue-500 hover:bg-blue-600 text-white\",\r\n },\r\n github: {\r\n label: \"Sponsor on GitHub\",\r\n color: \"bg-gray-800 hover:bg-black text-white\",\r\n },\r\n custom: {\r\n label: \"Support Us\",\r\n color: \"bg-indigo-600 hover:bg-indigo-700 text-white\",\r\n },\r\n};\r\n\r\nfunction getButtonClasses(link: SponsorLink, openInNewTab?: boolean) {\r\n const base =\r\n \"w-full rounded-xl px-5 py-3 font-medium transition-all duration-300 flex items-center justify-center gap-2\";\r\n\r\n const variant = link.variant ?? \"solid\";\r\n\r\n const defaultStyle =\r\n platformDefaults[link.platform] ?? platformDefaults.custom;\r\n\r\n const color = link.color ?? defaultStyle.color;\r\n\r\n if (variant === \"outline\") {\r\n return `${base} border border-current ${color.replace(\"bg-\", \"text-\")}`;\r\n }\r\n\r\n if (variant === \"ghost\") {\r\n return `${base} bg-transparent ${color.replace(\"bg-\", \"text-\")}`;\r\n }\r\n\r\n if (variant === \"gradient\") {\r\n return `${base} bg-gradient-to-r from-indigo-500 to-purple-600 text-white`;\r\n }\r\n\r\n return `${base} ${color}`;\r\n}\r\n\r\nfunction calculateProgress(current = 0, total = 1) {\r\n if (!total) return 0;\r\n return Math.min((current / total) * 100, 100);\r\n}\r\n\r\n/* =========================================================\r\n Component\r\n========================================================= */\r\n\r\nexport const SponsorWidget: React.FC<SponsorWidgetProps> = ({\r\n title,\r\n description,\r\n hero,\r\n previousSponsors,\r\n links,\r\n goal,\r\n layout = \"default\",\r\n theme = \"light\",\r\n className = \"\",\r\n containerClassName = \"\",\r\n renderSponsor,\r\n renderButton,\r\n openInNewTab = true,\r\n animation,\r\n}) => {\r\n const isDark = theme === \"dark\";\r\n\r\n const containerBase =\r\n \"max-w-3xl mx-auto rounded-2xl shadow-lg p-8 space-y-10 transition-all duration-300\";\r\n\r\n const themeClasses = isDark\r\n ? \"bg-gray-900 text-white\"\r\n : \"bg-white text-gray-900\";\r\n\r\n const animated =\r\n animation?.enabled !== false ? \"transition-all duration-300\" : \"\";\r\n\r\n return (\r\n <div className={`${containerBase} ${themeClasses} ${containerClassName}`}>\r\n {/* ================= HERO ================= */}\r\n {hero?.image && (\r\n <div className=\"flex justify-center\">\r\n <img\r\n src={hero.image}\r\n alt={hero.imageAlt ?? \"Sponsor Hero\"}\r\n className=\"w-24 h-24 object-contain rounded-xl\"\r\n title={hero.imageAlt ?? \"Sponsor Hero\"}\r\n />\r\n </div>\r\n )}\r\n\r\n {/* ================= TITLE ================= */}\r\n <div className=\"text-center space-y-4\">\r\n <h2 className=\"text-3xl font-bold\">{title}</h2>\r\n {description && (\r\n <p\r\n className={`max-w-xl mx-auto ${\r\n isDark ? \"text-gray-300\" : \"text-gray-600\"\r\n }`}\r\n >\r\n {description}\r\n </p>\r\n )}\r\n </div>\r\n\r\n {/* ================= FUNDING GOAL ================= */}\r\n {goal?.enabled && (\r\n <div className=\"space-y-3\">\r\n <div className=\"flex justify-between text-sm font-medium\">\r\n <span>\r\n Goal: {goal.currency ?? \"$\"}\r\n {goal.amount}\r\n </span>\r\n <span>\r\n Raised: {goal.currency ?? \"$\"}\r\n {goal.currentAmount ?? 0}\r\n </span>\r\n </div>\r\n\r\n <div\r\n className={`w-full h-3 rounded-full ${\r\n isDark ? \"bg-gray-700\" : \"bg-gray-200\"\r\n }`}\r\n >\r\n <div\r\n className=\"h-3 rounded-full bg-indigo-500 transition-all duration-500\"\r\n style={{\r\n width: `${calculateProgress(goal.currentAmount, goal.amount)}%`,\r\n }}\r\n />\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* ================= PREVIOUS SPONSORS ================= */}\r\n {previousSponsors && previousSponsors.length > 0 && (\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-lg font-semibold text-center\">\r\n 💛 Previous Sponsors\r\n </h3>\r\n\r\n <div\r\n className={`grid gap-4 ${\r\n layout === \"compact\"\r\n ? \"grid-cols-3\"\r\n : \"grid-cols-2 md:grid-cols-4\"\r\n }`}\r\n >\r\n {previousSponsors.map((sponsor, index) => {\r\n if (renderSponsor)\r\n return (\r\n <React.Fragment key={index}>\r\n {renderSponsor(sponsor)}\r\n </React.Fragment>\r\n );\r\n\r\n return (\r\n <a\r\n key={index}\r\n href={sponsor.profileUrl ?? \"#\"}\r\n target={openInNewTab ? \"_blank\" : \"_self\"}\r\n rel=\"noopener noreferrer\"\r\n className={`flex flex-col items-center justify-center p-4 rounded-xl shadow-sm hover:shadow-md ${\r\n animation?.hoverScale !== false ? \"hover:scale-105\" : \"\"\r\n } ${animated}`}\r\n >\r\n {sponsor.avatar && (\r\n <img\r\n src={sponsor.avatar}\r\n alt={sponsor.name}\r\n className=\"w-12 h-12 rounded-full object-cover mb-2\"\r\n />\r\n )}\r\n <span className=\"text-sm font-medium text-center\">\r\n {sponsor.name}\r\n </span>\r\n </a>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* ================= SUPPORT BUTTONS ================= */}\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-lg font-semibold text-center\">\r\n 🚀 Support This Project\r\n </h3>\r\n\r\n <div className=\"space-y-3\">\r\n {links.map((link, index) => {\r\n if (renderButton)\r\n return (\r\n <React.Fragment key={index}>\r\n {renderButton(link)}\r\n </React.Fragment>\r\n );\r\n\r\n const defaultStyle =\r\n platformDefaults[link.platform] ?? platformDefaults.custom;\r\n\r\n return (\r\n <a\r\n key={index}\r\n href={link.url}\r\n target={openInNewTab ? \"_blank\" : \"_self\"}\r\n rel=\"noopener noreferrer\"\r\n className={`${getButtonClasses(link, openInNewTab)} ${\r\n animation?.hoverScale !== false ? \"hover:scale-[1.02]\" : \"\"\r\n } ${animated}`}\r\n >\r\n {link.icon}\r\n {link.name ?? defaultStyle.label}\r\n </a>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n"],"names":["platformDefaults","buymeacoffee","label","color","patreon","opencollective","github","custom","getButtonClasses","link","openInNewTab","base","variant","defaultStyle","platform","replace","calculateProgress","current","total","Math","min","title","description","hero","previousSponsors","links","goal","layout","theme","className","containerClassName","renderSponsor","renderButton","animation","isDark","themeClasses","animated","enabled","_jsxs","children","image","_jsx","src","alt","imageAlt","currency","amount","currentAmount","style","width","length","map","sponsor","index","React","Fragment","href","profileUrl","target","rel","hoverScale","avatar","name","url","icon"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{jsxs as e,jsx as r}from"react/jsx-runtime";import t from"react";const a={buymeacoffee:{label:"Buy Me a Coffee",color:"bg-yellow-400 hover:bg-yellow-500 text-black"},patreon:{label:"Support on Patreon",color:"bg-orange-500 hover:bg-orange-600 text-white"},opencollective:{label:"Donate via OpenCollective",color:"bg-blue-500 hover:bg-blue-600 text-white"},github:{label:"Sponsor on GitHub",color:"bg-gray-800 hover:bg-black text-white"},custom:{label:"Support Us",color:"bg-indigo-600 hover:bg-indigo-700 text-white"}};function l(e,r){const t="w-full rounded-xl px-5 py-3 font-medium transition-all duration-300 flex items-center justify-center gap-2",l=e.variant??"solid",o=a[e.platform]??a.custom,n=e.color??o.color;return"outline"===l?`${t} border border-current ${n.replace("bg-","text-")}`:"ghost"===l?`${t} bg-transparent ${n.replace("bg-","text-")}`:"gradient"===l?`${t} bg-gradient-to-r from-indigo-500 to-purple-600 text-white`:`${t} ${n}`}function o(e=0,r=1){return r?Math.min(e/r*100,100):0}const n=({title:n,description:i,hero:c,previousSponsors:s,links:d,goal:m,layout:u="default",theme:h="light",className:g="",containerClassName:p="",renderSponsor:b,renderButton:f,openInNewTab:x=!0,animation:v})=>{const y="dark"===h,N=y?"bg-gray-900 text-white":"bg-white text-gray-900",w=!1!==v?.enabled?"transition-all duration-300":"";return e("div",{className:`max-w-3xl mx-auto rounded-2xl shadow-lg p-8 space-y-10 transition-all duration-300 ${N} ${p}`,children:[c?.image&&r("div",{className:"flex justify-center",children:r("img",{src:c.image,alt:c.imageAlt??"Sponsor Hero",className:"w-24 h-24 object-contain rounded-xl",title:c.imageAlt??"Sponsor Hero"})}),e("div",{className:"text-center space-y-4",children:[r("h2",{className:"text-3xl font-bold",children:n}),i&&r("p",{className:"max-w-xl mx-auto "+(y?"text-gray-300":"text-gray-600"),children:i})]}),m?.enabled&&e("div",{className:"space-y-3",children:[e("div",{className:"flex justify-between text-sm font-medium",children:[e("span",{children:["Goal: ",m.currency??"$",m.amount]}),e("span",{children:["Raised: ",m.currency??"$",m.currentAmount??0]})]}),r("div",{className:"w-full h-3 rounded-full "+(y?"bg-gray-700":"bg-gray-200"),children:r("div",{className:"h-3 rounded-full bg-indigo-500 transition-all duration-500",style:{width:`${o(m.currentAmount,m.amount)}%`}})})]}),s&&s.length>0&&e("div",{className:"space-y-4",children:[r("h3",{className:"text-lg font-semibold text-center",children:"💛 Previous Sponsors"}),r("div",{className:"grid gap-4 "+("compact"===u?"grid-cols-3":"grid-cols-2 md:grid-cols-4"),children:s.map((a,l)=>b?r(t.Fragment,{children:b(a)},l):e("a",{href:a.profileUrl??"#",target:x?"_blank":"_self",rel:"noopener noreferrer",className:`flex flex-col items-center justify-center p-4 rounded-xl shadow-sm hover:shadow-md ${!1!==v?.hoverScale?"hover:scale-105":""} ${w}`,children:[a.avatar&&r("img",{src:a.avatar,alt:a.name,className:"w-12 h-12 rounded-full object-cover mb-2"}),r("span",{className:"text-sm font-medium text-center",children:a.name})]},l))})]}),e("div",{className:"space-y-4",children:[r("h3",{className:"text-lg font-semibold text-center",children:"🚀 Support This Project"}),r("div",{className:"space-y-3",children:d.map((o,n)=>{if(f)return r(t.Fragment,{children:f(o)},n);const i=a[o.platform]??a.custom;return e("a",{href:o.url,target:x?"_blank":"_self",rel:"noopener noreferrer",className:`${l(o)} ${!1!==v?.hoverScale?"hover:scale-[1.02]":""} ${w}`,children:[o.icon,o.name??i.label]},n)})})]})]})};export{n as SponsorWidget};
2
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/components/SponsorWidget.tsx"],"sourcesContent":["import React from \"react\";\r\nimport { SponsorWidgetProps, SponsorLink, PreviousSponsor } from \"../types/Index\";\r\nimport \"../styles/Style.css\";\r\n\r\n/* =========================================================\r\n Internal Helpers\r\n========================================================= */\r\n\r\nconst platformDefaults: Record<string, { label: string; color: string }> = {\r\n buymeacoffee: {\r\n label: \"Buy Me a Coffee\",\r\n color: \"bg-yellow-400 hover:bg-yellow-500 text-black\",\r\n },\r\n patreon: {\r\n label: \"Support on Patreon\",\r\n color: \"bg-orange-500 hover:bg-orange-600 text-white\",\r\n },\r\n opencollective: {\r\n label: \"Donate via OpenCollective\",\r\n color: \"bg-blue-500 hover:bg-blue-600 text-white\",\r\n },\r\n github: {\r\n label: \"Sponsor on GitHub\",\r\n color: \"bg-gray-800 hover:bg-black text-white\",\r\n },\r\n custom: {\r\n label: \"Support Us\",\r\n color: \"bg-indigo-600 hover:bg-indigo-700 text-white\",\r\n },\r\n};\r\n\r\nfunction getButtonClasses(link: SponsorLink, openInNewTab?: boolean) {\r\n const base =\r\n \"w-full rounded-xl px-5 py-3 font-medium transition-all duration-300 flex items-center justify-center gap-2\";\r\n\r\n const variant = link.variant ?? \"solid\";\r\n\r\n const defaultStyle =\r\n platformDefaults[link.platform] ?? platformDefaults.custom;\r\n\r\n const color = link.color ?? defaultStyle.color;\r\n\r\n if (variant === \"outline\") {\r\n return `${base} border border-current ${color.replace(\"bg-\", \"text-\")}`;\r\n }\r\n\r\n if (variant === \"ghost\") {\r\n return `${base} bg-transparent ${color.replace(\"bg-\", \"text-\")}`;\r\n }\r\n\r\n if (variant === \"gradient\") {\r\n return `${base} bg-gradient-to-r from-indigo-500 to-purple-600 text-white`;\r\n }\r\n\r\n return `${base} ${color}`;\r\n}\r\n\r\nfunction calculateProgress(current = 0, total = 1) {\r\n if (!total) return 0;\r\n return Math.min((current / total) * 100, 100);\r\n}\r\n\r\n/* =========================================================\r\n Component\r\n========================================================= */\r\n\r\nexport const SponsorWidget: React.FC<SponsorWidgetProps> = ({\r\n title,\r\n description,\r\n hero,\r\n previousSponsors,\r\n links,\r\n goal,\r\n layout = \"default\",\r\n theme = \"light\",\r\n className = \"\",\r\n containerClassName = \"\",\r\n renderSponsor,\r\n renderButton,\r\n openInNewTab = true,\r\n animation,\r\n}) => {\r\n const isDark = theme === \"dark\";\r\n\r\n const containerBase =\r\n \"max-w-3xl mx-auto rounded-2xl shadow-lg p-8 space-y-10 transition-all duration-300\";\r\n\r\n const themeClasses = isDark\r\n ? \"bg-gray-900 text-white\"\r\n : \"bg-white text-gray-900\";\r\n\r\n const animated =\r\n animation?.enabled !== false ? \"transition-all duration-300\" : \"\";\r\n\r\n return (\r\n <div className={`${containerBase} ${themeClasses} ${containerClassName}`}>\r\n {/* ================= HERO ================= */}\r\n {hero?.image && (\r\n <div className=\"flex justify-center\">\r\n <img\r\n src={hero.image}\r\n alt={hero.imageAlt ?? \"Sponsor Hero\"}\r\n className=\"w-24 h-24 object-contain rounded-xl\"\r\n title={hero.imageAlt ?? \"Sponsor Hero\"}\r\n />\r\n </div>\r\n )}\r\n\r\n {/* ================= TITLE ================= */}\r\n <div className=\"text-center space-y-4\">\r\n <h2 className=\"text-3xl font-bold\">{title}</h2>\r\n {description && (\r\n <p\r\n className={`max-w-xl mx-auto ${\r\n isDark ? \"text-gray-300\" : \"text-gray-600\"\r\n }`}\r\n >\r\n {description}\r\n </p>\r\n )}\r\n </div>\r\n\r\n {/* ================= FUNDING GOAL ================= */}\r\n {goal?.enabled && (\r\n <div className=\"space-y-3\">\r\n <div className=\"flex justify-between text-sm font-medium\">\r\n <span>\r\n Goal: {goal.currency ?? \"$\"}\r\n {goal.amount}\r\n </span>\r\n <span>\r\n Raised: {goal.currency ?? \"$\"}\r\n {goal.currentAmount ?? 0}\r\n </span>\r\n </div>\r\n\r\n <div\r\n className={`w-full h-3 rounded-full ${\r\n isDark ? \"bg-gray-700\" : \"bg-gray-200\"\r\n }`}\r\n >\r\n <div\r\n className=\"h-3 rounded-full bg-indigo-500 transition-all duration-500\"\r\n style={{\r\n width: `${calculateProgress(goal.currentAmount, goal.amount)}%`,\r\n }}\r\n />\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* ================= PREVIOUS SPONSORS ================= */}\r\n {previousSponsors && previousSponsors.length > 0 && (\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-lg font-semibold text-center\">\r\n 💛 Previous Sponsors\r\n </h3>\r\n\r\n <div\r\n className={`grid gap-4 ${\r\n layout === \"compact\"\r\n ? \"grid-cols-3\"\r\n : \"grid-cols-2 md:grid-cols-4\"\r\n }`}\r\n >\r\n {previousSponsors.map((sponsor, index) => {\r\n if (renderSponsor)\r\n return (\r\n <React.Fragment key={index}>\r\n {renderSponsor(sponsor)}\r\n </React.Fragment>\r\n );\r\n\r\n return (\r\n <a\r\n key={index}\r\n href={sponsor.profileUrl ?? \"#\"}\r\n target={openInNewTab ? \"_blank\" : \"_self\"}\r\n rel=\"noopener noreferrer\"\r\n className={`flex flex-col items-center justify-center p-4 rounded-xl shadow-sm hover:shadow-md ${\r\n animation?.hoverScale !== false ? \"hover:scale-105\" : \"\"\r\n } ${animated}`}\r\n >\r\n {sponsor.avatar && (\r\n <img\r\n src={sponsor.avatar}\r\n alt={sponsor.name}\r\n className=\"w-12 h-12 rounded-full object-cover mb-2\"\r\n />\r\n )}\r\n <span className=\"text-sm font-medium text-center\">\r\n {sponsor.name}\r\n </span>\r\n </a>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* ================= SUPPORT BUTTONS ================= */}\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-lg font-semibold text-center\">\r\n 🚀 Support This Project\r\n </h3>\r\n\r\n <div className=\"space-y-3\">\r\n {links.map((link, index) => {\r\n if (renderButton)\r\n return (\r\n <React.Fragment key={index}>\r\n {renderButton(link)}\r\n </React.Fragment>\r\n );\r\n\r\n const defaultStyle =\r\n platformDefaults[link.platform] ?? platformDefaults.custom;\r\n\r\n return (\r\n <a\r\n key={index}\r\n href={link.url}\r\n target={openInNewTab ? \"_blank\" : \"_self\"}\r\n rel=\"noopener noreferrer\"\r\n className={`${getButtonClasses(link, openInNewTab)} ${\r\n animation?.hoverScale !== false ? \"hover:scale-[1.02]\" : \"\"\r\n } ${animated}`}\r\n >\r\n {link.icon}\r\n {link.name ?? defaultStyle.label}\r\n </a>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n"],"names":["platformDefaults","buymeacoffee","label","color","patreon","opencollective","github","custom","getButtonClasses","link","openInNewTab","base","variant","defaultStyle","platform","replace","calculateProgress","current","total","Math","min","SponsorWidget","title","description","hero","previousSponsors","links","goal","layout","theme","className","containerClassName","renderSponsor","renderButton","animation","isDark","themeClasses","animated","enabled","_jsxs","children","image","_jsx","src","alt","imageAlt","currency","amount","currentAmount","style","width","length","map","sponsor","index","React","Fragment","href","profileUrl","target","rel","hoverScale","avatar","name","url","icon"],"mappings":"uEAQA,MAAMA,EAAqE,CACzEC,aAAc,CACZC,MAAO,kBACPC,MAAO,gDAETC,QAAS,CACPF,MAAO,qBACPC,MAAO,gDAETE,eAAgB,CACdH,MAAO,4BACPC,MAAO,4CAETG,OAAQ,CACNJ,MAAO,oBACPC,MAAO,yCAETI,OAAQ,CACNL,MAAO,aACPC,MAAO,iDAIX,SAASK,EAAiBC,EAAmBC,GAC3C,MAAMC,EACJ,6GAEIC,EAAUH,EAAKG,SAAW,QAE1BC,EACJb,EAAiBS,EAAKK,WAAad,EAAiBO,OAEhDJ,EAAQM,EAAKN,OAASU,EAAaV,MAEzC,MAAgB,YAAZS,EACK,GAAGD,2BAA8BR,EAAMY,QAAQ,MAAO,WAG/C,UAAZH,EACK,GAAGD,oBAAuBR,EAAMY,QAAQ,MAAO,WAGxC,aAAZH,EACK,GAAGD,8DAGL,GAAGA,KAAQR,GACpB,CAEA,SAASa,EAAkBC,EAAU,EAAGC,EAAQ,GAC9C,OAAKA,EACEC,KAAKC,IAAKH,EAAUC,EAAS,IAAK,KADtB,CAErB,OAMaG,EAA8C,EACzDC,QACAC,cACAC,OACAC,mBACAC,QACAC,OACAC,SAAS,UACTC,QAAQ,QACRC,YAAY,GACZC,qBAAqB,GACrBC,gBACAC,eACAvB,gBAAe,EACfwB,gBAEA,MAAMC,EAAmB,SAAVN,EAKTO,EAAeD,EACjB,yBACA,yBAEEE,GACmB,IAAvBH,GAAWI,QAAoB,8BAAgC,GAEjE,OACEC,EAAA,MAAA,CAAKT,UAAW,sFAAoBM,KAAgBL,IAAoBS,SAAA,CAErEhB,GAAMiB,OACLC,EAAA,MAAA,CAAKZ,UAAU,sBAAqBU,SAClCE,EAAA,MAAA,CACEC,IAAKnB,EAAKiB,MACVG,IAAKpB,EAAKqB,UAAY,eACtBf,UAAU,sCACVR,MAAOE,EAAKqB,UAAY,mBAM9BN,SAAKT,UAAU,wBAAuBU,SAAA,CACpCE,QAAIZ,UAAU,qBAAoBU,SAAElB,IACnCC,GACCmB,EAAA,IAAA,CACEZ,UAAW,qBACTK,EAAS,gBAAkB,iBAC3BK,SAEDjB,OAMNI,GAAMW,SACLC,EAAA,MAAA,CAAKT,UAAU,YAAWU,SAAA,CACxBD,EAAA,MAAA,CAAKT,UAAU,2CAA0CU,SAAA,CACvDD,EAAA,OAAA,CAAAC,SAAA,CAAA,SACSb,EAAKmB,UAAY,IACvBnB,EAAKoB,UAERR,EAAA,OAAA,CAAAC,SAAA,CAAA,WACWb,EAAKmB,UAAY,IACzBnB,EAAKqB,eAAiB,QAI3BN,SACEZ,UAAW,4BACTK,EAAS,cAAgB,eACzBK,SAEFE,SACEZ,UAAU,6DACVmB,MAAO,CACLC,MAAO,GAAGlC,EAAkBW,EAAKqB,cAAerB,EAAKoB,mBAQ9DtB,GAAoBA,EAAiB0B,OAAS,GAC7CZ,EAAA,MAAA,CAAKT,UAAU,YAAWU,SAAA,CACxBE,EAAA,KAAA,CAAIZ,UAAU,oCAAmCU,SAAA,yBAIjDE,EAAA,MAAA,CACEZ,UAAW,eACE,YAAXF,EACI,cACA,8BACJY,SAEDf,EAAiB2B,IAAI,CAACC,EAASC,IAC1BtB,EAEAU,EAACa,EAAMC,SAAQ,CAAAhB,SACZR,EAAcqB,IADIC,GAMvBf,EAAA,IAAA,CAEEkB,KAAMJ,EAAQK,YAAc,IAC5BC,OAAQjD,EAAe,SAAW,QAClCkD,IAAI,sBACJ9B,UAAW,uFACiB,IAA1BI,GAAW2B,WAAuB,kBAAoB,MACpDxB,IAAUG,SAAA,CAEba,EAAQS,QACPpB,EAAA,MAAA,CACEC,IAAKU,EAAQS,OACblB,IAAKS,EAAQU,KACbjC,UAAU,6CAGdY,EAAA,OAAA,CAAMZ,UAAU,kCAAiCU,SAC9Ca,EAAQU,SAhBNT,SA0BjBf,EAAA,MAAA,CAAKT,UAAU,YAAWU,SAAA,CACxBE,EAAA,KAAA,CAAIZ,UAAU,oCAAmCU,SAAA,4BAIjDE,EAAA,MAAA,CAAKZ,UAAU,YAAWU,SACvBd,EAAM0B,IAAI,CAAC3C,EAAM6C,KAChB,GAAIrB,EACF,OACES,EAACa,EAAMC,SAAQ,CAAAhB,SACZP,EAAaxB,IADK6C,GAKzB,MAAMzC,EACJb,EAAiBS,EAAKK,WAAad,EAAiBO,OAEtD,OACEgC,EAAA,IAAA,CAEEkB,KAAMhD,EAAKuD,IACXL,OAAQjD,EAAe,SAAW,QAClCkD,IAAI,sBACJ9B,UAAW,GAAGtB,EAAiBC,OACH,IAA1ByB,GAAW2B,WAAuB,qBAAuB,MACvDxB,IAAUG,SAAA,CAEb/B,EAAKwD,KACLxD,EAAKsD,MAAQlD,EAAaX,QATtBoD"}
@@ -0,0 +1,2 @@
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react/jsx-runtime"),require("react")):"function"==typeof define&&define.amd?define(["exports","react/jsx-runtime","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).OpenSponsorWidget={},e.jsxRuntime,e.React)}(this,function(e,t,r){"use strict";const a={buymeacoffee:{label:"Buy Me a Coffee",color:"bg-yellow-400 hover:bg-yellow-500 text-black"},patreon:{label:"Support on Patreon",color:"bg-orange-500 hover:bg-orange-600 text-white"},opencollective:{label:"Donate via OpenCollective",color:"bg-blue-500 hover:bg-blue-600 text-white"},github:{label:"Sponsor on GitHub",color:"bg-gray-800 hover:bg-black text-white"},custom:{label:"Support Us",color:"bg-indigo-600 hover:bg-indigo-700 text-white"}};function o(e,t){const r="w-full rounded-xl px-5 py-3 font-medium transition-all duration-300 flex items-center justify-center gap-2",o=e.variant??"solid",l=a[e.platform]??a.custom,n=e.color??l.color;return"outline"===o?`${r} border border-current ${n.replace("bg-","text-")}`:"ghost"===o?`${r} bg-transparent ${n.replace("bg-","text-")}`:"gradient"===o?`${r} bg-gradient-to-r from-indigo-500 to-purple-600 text-white`:`${r} ${n}`}function l(e=0,t=1){return t?Math.min(e/t*100,100):0}e.SponsorWidget=({title:e,description:n,hero:s,previousSponsors:i,links:c,goal:d,layout:m="default",theme:u="light",className:x="",containerClassName:g="",renderSponsor:h,renderButton:p,openInNewTab:f=!0,animation:b})=>{const j="dark"===u,v=j?"bg-gray-900 text-white":"bg-white text-gray-900",y=!1!==b?.enabled?"transition-all duration-300":"";return t.jsxs("div",{className:`max-w-3xl mx-auto rounded-2xl shadow-lg p-8 space-y-10 transition-all duration-300 ${v} ${g}`,children:[s?.image&&t.jsx("div",{className:"flex justify-center",children:t.jsx("img",{src:s.image,alt:s.imageAlt??"Sponsor Hero",className:"w-24 h-24 object-contain rounded-xl",title:s.imageAlt??"Sponsor Hero"})}),t.jsxs("div",{className:"text-center space-y-4",children:[t.jsx("h2",{className:"text-3xl font-bold",children:e}),n&&t.jsx("p",{className:"max-w-xl mx-auto "+(j?"text-gray-300":"text-gray-600"),children:n})]}),d?.enabled&&t.jsxs("div",{className:"space-y-3",children:[t.jsxs("div",{className:"flex justify-between text-sm font-medium",children:[t.jsxs("span",{children:["Goal: ",d.currency??"$",d.amount]}),t.jsxs("span",{children:["Raised: ",d.currency??"$",d.currentAmount??0]})]}),t.jsx("div",{className:"w-full h-3 rounded-full "+(j?"bg-gray-700":"bg-gray-200"),children:t.jsx("div",{className:"h-3 rounded-full bg-indigo-500 transition-all duration-500",style:{width:`${l(d.currentAmount,d.amount)}%`}})})]}),i&&i.length>0&&t.jsxs("div",{className:"space-y-4",children:[t.jsx("h3",{className:"text-lg font-semibold text-center",children:"💛 Previous Sponsors"}),t.jsx("div",{className:"grid gap-4 "+("compact"===m?"grid-cols-3":"grid-cols-2 md:grid-cols-4"),children:i.map((e,a)=>h?t.jsx(r.Fragment,{children:h(e)},a):t.jsxs("a",{href:e.profileUrl??"#",target:f?"_blank":"_self",rel:"noopener noreferrer",className:`flex flex-col items-center justify-center p-4 rounded-xl shadow-sm hover:shadow-md ${!1!==b?.hoverScale?"hover:scale-105":""} ${y}`,children:[e.avatar&&t.jsx("img",{src:e.avatar,alt:e.name,className:"w-12 h-12 rounded-full object-cover mb-2"}),t.jsx("span",{className:"text-sm font-medium text-center",children:e.name})]},a))})]}),t.jsxs("div",{className:"space-y-4",children:[t.jsx("h3",{className:"text-lg font-semibold text-center",children:"🚀 Support This Project"}),t.jsx("div",{className:"space-y-3",children:c.map((e,l)=>{if(p)return t.jsx(r.Fragment,{children:p(e)},l);const n=a[e.platform]??a.custom;return t.jsxs("a",{href:e.url,target:f?"_blank":"_self",rel:"noopener noreferrer",className:`${o(e)} ${!1!==b?.hoverScale?"hover:scale-[1.02]":""} ${y}`,children:[e.icon,e.name??n.label]},l)})})]})]})}});
2
+ //# sourceMappingURL=index.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.umd.js","sources":["../src/components/SponsorWidget.tsx"],"sourcesContent":["import React from \"react\";\r\nimport { SponsorWidgetProps, SponsorLink, PreviousSponsor } from \"../types/Index\";\r\nimport \"../styles/Style.css\";\r\n\r\n/* =========================================================\r\n Internal Helpers\r\n========================================================= */\r\n\r\nconst platformDefaults: Record<string, { label: string; color: string }> = {\r\n buymeacoffee: {\r\n label: \"Buy Me a Coffee\",\r\n color: \"bg-yellow-400 hover:bg-yellow-500 text-black\",\r\n },\r\n patreon: {\r\n label: \"Support on Patreon\",\r\n color: \"bg-orange-500 hover:bg-orange-600 text-white\",\r\n },\r\n opencollective: {\r\n label: \"Donate via OpenCollective\",\r\n color: \"bg-blue-500 hover:bg-blue-600 text-white\",\r\n },\r\n github: {\r\n label: \"Sponsor on GitHub\",\r\n color: \"bg-gray-800 hover:bg-black text-white\",\r\n },\r\n custom: {\r\n label: \"Support Us\",\r\n color: \"bg-indigo-600 hover:bg-indigo-700 text-white\",\r\n },\r\n};\r\n\r\nfunction getButtonClasses(link: SponsorLink, openInNewTab?: boolean) {\r\n const base =\r\n \"w-full rounded-xl px-5 py-3 font-medium transition-all duration-300 flex items-center justify-center gap-2\";\r\n\r\n const variant = link.variant ?? \"solid\";\r\n\r\n const defaultStyle =\r\n platformDefaults[link.platform] ?? platformDefaults.custom;\r\n\r\n const color = link.color ?? defaultStyle.color;\r\n\r\n if (variant === \"outline\") {\r\n return `${base} border border-current ${color.replace(\"bg-\", \"text-\")}`;\r\n }\r\n\r\n if (variant === \"ghost\") {\r\n return `${base} bg-transparent ${color.replace(\"bg-\", \"text-\")}`;\r\n }\r\n\r\n if (variant === \"gradient\") {\r\n return `${base} bg-gradient-to-r from-indigo-500 to-purple-600 text-white`;\r\n }\r\n\r\n return `${base} ${color}`;\r\n}\r\n\r\nfunction calculateProgress(current = 0, total = 1) {\r\n if (!total) return 0;\r\n return Math.min((current / total) * 100, 100);\r\n}\r\n\r\n/* =========================================================\r\n Component\r\n========================================================= */\r\n\r\nexport const SponsorWidget: React.FC<SponsorWidgetProps> = ({\r\n title,\r\n description,\r\n hero,\r\n previousSponsors,\r\n links,\r\n goal,\r\n layout = \"default\",\r\n theme = \"light\",\r\n className = \"\",\r\n containerClassName = \"\",\r\n renderSponsor,\r\n renderButton,\r\n openInNewTab = true,\r\n animation,\r\n}) => {\r\n const isDark = theme === \"dark\";\r\n\r\n const containerBase =\r\n \"max-w-3xl mx-auto rounded-2xl shadow-lg p-8 space-y-10 transition-all duration-300\";\r\n\r\n const themeClasses = isDark\r\n ? \"bg-gray-900 text-white\"\r\n : \"bg-white text-gray-900\";\r\n\r\n const animated =\r\n animation?.enabled !== false ? \"transition-all duration-300\" : \"\";\r\n\r\n return (\r\n <div className={`${containerBase} ${themeClasses} ${containerClassName}`}>\r\n {/* ================= HERO ================= */}\r\n {hero?.image && (\r\n <div className=\"flex justify-center\">\r\n <img\r\n src={hero.image}\r\n alt={hero.imageAlt ?? \"Sponsor Hero\"}\r\n className=\"w-24 h-24 object-contain rounded-xl\"\r\n title={hero.imageAlt ?? \"Sponsor Hero\"}\r\n />\r\n </div>\r\n )}\r\n\r\n {/* ================= TITLE ================= */}\r\n <div className=\"text-center space-y-4\">\r\n <h2 className=\"text-3xl font-bold\">{title}</h2>\r\n {description && (\r\n <p\r\n className={`max-w-xl mx-auto ${\r\n isDark ? \"text-gray-300\" : \"text-gray-600\"\r\n }`}\r\n >\r\n {description}\r\n </p>\r\n )}\r\n </div>\r\n\r\n {/* ================= FUNDING GOAL ================= */}\r\n {goal?.enabled && (\r\n <div className=\"space-y-3\">\r\n <div className=\"flex justify-between text-sm font-medium\">\r\n <span>\r\n Goal: {goal.currency ?? \"$\"}\r\n {goal.amount}\r\n </span>\r\n <span>\r\n Raised: {goal.currency ?? \"$\"}\r\n {goal.currentAmount ?? 0}\r\n </span>\r\n </div>\r\n\r\n <div\r\n className={`w-full h-3 rounded-full ${\r\n isDark ? \"bg-gray-700\" : \"bg-gray-200\"\r\n }`}\r\n >\r\n <div\r\n className=\"h-3 rounded-full bg-indigo-500 transition-all duration-500\"\r\n style={{\r\n width: `${calculateProgress(goal.currentAmount, goal.amount)}%`,\r\n }}\r\n />\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* ================= PREVIOUS SPONSORS ================= */}\r\n {previousSponsors && previousSponsors.length > 0 && (\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-lg font-semibold text-center\">\r\n 💛 Previous Sponsors\r\n </h3>\r\n\r\n <div\r\n className={`grid gap-4 ${\r\n layout === \"compact\"\r\n ? \"grid-cols-3\"\r\n : \"grid-cols-2 md:grid-cols-4\"\r\n }`}\r\n >\r\n {previousSponsors.map((sponsor, index) => {\r\n if (renderSponsor)\r\n return (\r\n <React.Fragment key={index}>\r\n {renderSponsor(sponsor)}\r\n </React.Fragment>\r\n );\r\n\r\n return (\r\n <a\r\n key={index}\r\n href={sponsor.profileUrl ?? \"#\"}\r\n target={openInNewTab ? \"_blank\" : \"_self\"}\r\n rel=\"noopener noreferrer\"\r\n className={`flex flex-col items-center justify-center p-4 rounded-xl shadow-sm hover:shadow-md ${\r\n animation?.hoverScale !== false ? \"hover:scale-105\" : \"\"\r\n } ${animated}`}\r\n >\r\n {sponsor.avatar && (\r\n <img\r\n src={sponsor.avatar}\r\n alt={sponsor.name}\r\n className=\"w-12 h-12 rounded-full object-cover mb-2\"\r\n />\r\n )}\r\n <span className=\"text-sm font-medium text-center\">\r\n {sponsor.name}\r\n </span>\r\n </a>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* ================= SUPPORT BUTTONS ================= */}\r\n <div className=\"space-y-4\">\r\n <h3 className=\"text-lg font-semibold text-center\">\r\n 🚀 Support This Project\r\n </h3>\r\n\r\n <div className=\"space-y-3\">\r\n {links.map((link, index) => {\r\n if (renderButton)\r\n return (\r\n <React.Fragment key={index}>\r\n {renderButton(link)}\r\n </React.Fragment>\r\n );\r\n\r\n const defaultStyle =\r\n platformDefaults[link.platform] ?? platformDefaults.custom;\r\n\r\n return (\r\n <a\r\n key={index}\r\n href={link.url}\r\n target={openInNewTab ? \"_blank\" : \"_self\"}\r\n rel=\"noopener noreferrer\"\r\n className={`${getButtonClasses(link, openInNewTab)} ${\r\n animation?.hoverScale !== false ? \"hover:scale-[1.02]\" : \"\"\r\n } ${animated}`}\r\n >\r\n {link.icon}\r\n {link.name ?? defaultStyle.label}\r\n </a>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n"],"names":["platformDefaults","buymeacoffee","label","color","patreon","opencollective","github","custom","getButtonClasses","link","openInNewTab","base","variant","defaultStyle","platform","replace","calculateProgress","current","total","Math","min","title","description","hero","previousSponsors","links","goal","layout","theme","className","containerClassName","renderSponsor","renderButton","animation","isDark","themeClasses","animated","enabled","_jsxs","children","image","_jsx","src","alt","imageAlt","currency","amount","currentAmount","style","width","length","map","sponsor","index","React","Fragment","href","profileUrl","target","rel","hoverScale","avatar","name","url","icon"],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import { ReactNode } from "react";
2
+ export type SponsorPlatform = "buymeacoffee" | "patreon" | "opencollective" | "github" | "custom";
3
+ export interface PreviousSponsor {
4
+ name: string;
5
+ avatar?: string;
6
+ profileUrl?: string;
7
+ }
8
+ export interface SponsorLink {
9
+ platform: SponsorPlatform;
10
+ name?: string;
11
+ url: string;
12
+ icon?: ReactNode;
13
+ color?: string;
14
+ variant?: ButtonVariant;
15
+ }
16
+ export type ButtonVariant = "solid" | "outline" | "ghost" | "gradient";
17
+ export type SponsorTheme = "light" | "dark";
18
+ export type SponsorLayout = "default" | "compact" | "minimal" | "card" | "inline";
19
+ export interface FundingGoal {
20
+ enabled?: boolean;
21
+ amount: number;
22
+ currency?: string;
23
+ currentAmount?: number;
24
+ }
25
+ export interface HeroSection {
26
+ image?: string;
27
+ imageAlt?: string;
28
+ }
29
+ export interface AnimationConfig {
30
+ enabled?: boolean;
31
+ hoverScale?: boolean;
32
+ fadeIn?: boolean;
33
+ duration?: number;
34
+ }
35
+ export interface SponsorWidgetProps {
36
+ title: string;
37
+ description?: string;
38
+ hero?: HeroSection;
39
+ previousSponsors?: PreviousSponsor[];
40
+ links: SponsorLink[];
41
+ goal?: FundingGoal;
42
+ layout?: SponsorLayout;
43
+ theme?: SponsorTheme;
44
+ className?: string;
45
+ containerClassName?: string;
46
+ renderSponsor?: (sponsor: PreviousSponsor) => ReactNode;
47
+ renderButton?: (link: SponsorLink) => ReactNode;
48
+ openInNewTab?: boolean;
49
+ animation?: AnimationConfig;
50
+ }
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "open-sponsor-widget",
3
+ "version": "1.0.0",
4
+ "description": "Reusable React widget to add a sponsored support section to your website.",
5
+ "author": "Rahul",
6
+ "license": "MIT",
7
+ "type": "module",
8
+
9
+ "main": "dist/index.cjs.js",
10
+ "module": "dist/index.esm.js",
11
+ "unpkg": "dist/index.umd.js",
12
+ "jsdelivr": "dist/index.umd.js",
13
+ "types": "dist/index.d.ts",
14
+
15
+ "files": ["dist"],
16
+
17
+ "exports": {
18
+ ".": {
19
+ "import": "./dist/index.esm.js",
20
+ "require": "./dist/index.cjs.js",
21
+ "types": "./dist/index.d.ts"
22
+ }
23
+ },
24
+
25
+ "sideEffects": false,
26
+
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/rahul-vyas-dev/open-sponsor-widget"
30
+ },
31
+
32
+ "homepage": "https://github.com/rahul-vyas-dev/open-sponsor-widget#readme",
33
+
34
+ "bugs": {
35
+ "url": "https://github.com/rahul-vyas-dev/open-sponsor-widget/issues"
36
+ },
37
+
38
+ "scripts": {
39
+ "build": "rollup -c",
40
+ "prepublishOnly": "npm run build"
41
+ },
42
+
43
+ "peerDependencies": {
44
+ "react": ">=18",
45
+ "react-dom": ">=18"
46
+ },
47
+
48
+ "dependencies": {
49
+ "tslib": "^2.8.1"
50
+ },
51
+
52
+ "devDependencies": {
53
+ "@rollup/plugin-commonjs": "^29.0.0",
54
+ "@rollup/plugin-node-resolve": "^16.0.3",
55
+ "@rollup/plugin-terser": "^0.4.4",
56
+ "@rollup/plugin-typescript": "^12.3.0",
57
+ "@types/react": "^19.2.14",
58
+ "autoprefixer": "^10.4.24",
59
+ "postcss": "^8.5.6",
60
+ "rollup": "^4.59.0",
61
+ "rollup-plugin-dts": "^6.3.0",
62
+ "rollup-plugin-peer-deps-external": "^2.2.4",
63
+ "rollup-plugin-postcss": "^4.0.2",
64
+ "tailwindcss": "^4.2.1",
65
+ "typescript": "^5.9.3",
66
+ "@tailwindcss/postcss": "^4.2.1"
67
+ }
68
+ }