rails_tipjar 0.3.0 → 1.0.1
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.
- checksums.yaml +4 -4
- data/README.md +113 -99
- data/app/helpers/tipjar_helper.rb +280 -49
- data/app/views/tipjar/_button.html.erb +5 -5
- data/lib/generators/tipjar/install/install_generator.rb +28 -21
- data/lib/rails_tipjar/configuration.rb +2 -2
- data/lib/rails_tipjar/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2acacf788da12d40f7f2b20ae9042e0adf416bb17475c20cd309a737120143fa
|
4
|
+
data.tar.gz: ed97fb19a2935a38bc26c29c86be548c1d33a08c33081dfc336e88af83957a36
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 604ce459a6e71e0b16aef786e0c146b01c3fe4805dbf3fbf880e8df105168520b8fe967dbc8dd195a6efd16622cf0be56c9edee722073e9fb88873b293f5563c
|
7
|
+
data.tar.gz: 9adf68a419979b2d4e5e8a96d3ec92a0cf4135e074cf4c03c6d17879d056cbd08861d12b5e1561a5436c7af5d4f7d668279b3976684f65fb6e4fa5f117a67b20
|
data/README.md
CHANGED
@@ -42,6 +42,10 @@ Then execute:
|
|
42
42
|
|
43
43
|
```bash
|
44
44
|
bundle install
|
45
|
+
```
|
46
|
+
|
47
|
+
Optionally run the generator (only needed for backwards compatibility with v0.3.0 and earlier):
|
48
|
+
```bash
|
45
49
|
rails generate tipjar:install
|
46
50
|
```
|
47
51
|
|
@@ -60,31 +64,58 @@ Choose your preferred payment provider and create payment links:
|
|
60
64
|
|
61
65
|
Create links for different amounts or use a single link that accepts custom amounts.
|
62
66
|
|
63
|
-
### 2.
|
67
|
+
### 2. Add to Your Views
|
64
68
|
|
65
|
-
|
69
|
+
No configuration file needed! Simply use the helper in your views with all options:
|
66
70
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
71
|
+
#### Simple Button (Direct Link)
|
72
|
+
|
73
|
+
Add directly to any view:
|
74
|
+
|
75
|
+
```erb
|
76
|
+
<!-- Basic usage with default jar icon -->
|
77
|
+
<%= tip_jar payment_link: 'https://your.payment.link' %>
|
78
|
+
|
79
|
+
<!-- With all customization options -->
|
80
|
+
<%= tip_jar payment_link: 'https://your.payment.link',
|
81
|
+
message: 'Support This Project', # Text shown on hover
|
82
|
+
icon: :heart, # :coffee, :heart, :star, :dollar, :jar, or custom SVG
|
83
|
+
position: :bottom_right, # :bottom_right, :bottom_left, :top_right, :top_left
|
84
|
+
color: '#8b5cf6', # Button background color
|
85
|
+
text_color: '#ffffff', # Button text color
|
86
|
+
pulse: true, # Enable pulsing animation
|
87
|
+
z_index: 1000, # Stack order
|
88
|
+
class: 'my-custom-class' %> # Additional CSS classes
|
83
89
|
```
|
84
90
|
|
85
|
-
|
91
|
+
#### Modal Mode (Multiple Payment Options)
|
86
92
|
|
87
|
-
|
93
|
+
```erb
|
94
|
+
<!-- Modal with multiple payment amounts -->
|
95
|
+
<%= tip_jar payment_links: {
|
96
|
+
small: 'https://your-provider.com/tip-5',
|
97
|
+
medium: 'https://your-provider.com/tip-10',
|
98
|
+
large: 'https://your-provider.com/tip-25'
|
99
|
+
},
|
100
|
+
modal_title: 'Support my work',
|
101
|
+
modal_description: 'Your support helps me continue creating.',
|
102
|
+
custom_amounts: [
|
103
|
+
{ amount: 5, label: '$5', default: false },
|
104
|
+
{ amount: 10, label: '$10', default: true },
|
105
|
+
{ amount: 25, label: '$25', default: false }
|
106
|
+
],
|
107
|
+
theme: :light, # :light, :dark, :auto
|
108
|
+
analytics_enabled: true %>
|
109
|
+
|
110
|
+
<!-- Force modal mode with single link -->
|
111
|
+
<%= tip_jar payment_link: 'https://your.payment.link',
|
112
|
+
use_modal: true,
|
113
|
+
modal_title: 'Choose your support amount' %>
|
114
|
+
```
|
115
|
+
|
116
|
+
#### In Layouts
|
117
|
+
|
118
|
+
Add to `app/views/layouts/application.html.erb`:
|
88
119
|
|
89
120
|
```erb
|
90
121
|
<!DOCTYPE html>
|
@@ -95,92 +126,61 @@ In `app/views/layouts/application.html.erb`:
|
|
95
126
|
<body>
|
96
127
|
<%= yield %>
|
97
128
|
|
98
|
-
<!-- Add tip jar button -->
|
99
|
-
<%=
|
129
|
+
<!-- Add floating tip jar button -->
|
130
|
+
<%= tip_jar payment_link: 'https://your.payment.link',
|
131
|
+
position: :bottom_right %>
|
100
132
|
</body>
|
101
133
|
</html>
|
102
134
|
```
|
103
135
|
|
104
136
|
That's it! You now have a working tip jar on your site.
|
105
137
|
|
106
|
-
##
|
138
|
+
## Helper Options
|
107
139
|
|
108
|
-
|
109
|
-
RailsTipjar.configure do |config|
|
110
|
-
# Simple mode - just one payment link (no modal)
|
111
|
-
config.payment_link = "https://your-payment-link.com"
|
112
|
-
|
113
|
-
# Modal mode - multiple payment links
|
114
|
-
config.payment_links = {
|
115
|
-
small: "...",
|
116
|
-
medium: "...",
|
117
|
-
large: "...",
|
118
|
-
custom: "..." # Optional: for custom amounts
|
119
|
-
}
|
120
|
-
config.use_modal = true # Force modal even with single link
|
121
|
-
|
122
|
-
# Button position
|
123
|
-
# Options: :bottom_right, :bottom_left, :top_right, :top_left
|
124
|
-
config.position = :bottom_right
|
125
|
-
|
126
|
-
# Button icon
|
127
|
-
# Options: :coffee, :heart, :star, :dollar, :jar, or custom SVG string
|
128
|
-
config.icon = :coffee
|
129
|
-
|
130
|
-
# Button colors (hex values)
|
131
|
-
config.color = "#3b82f6" # Background color (default: blue)
|
132
|
-
config.text_color = "#ffffff" # Text color (default: white)
|
133
|
-
|
134
|
-
# Pulsing animation
|
135
|
-
config.pulse = false # Set to true to enable pulsing effect
|
136
|
-
|
137
|
-
# Theme for modal
|
138
|
-
# Options: :light, :dark, :auto
|
139
|
-
config.theme = :light
|
140
|
-
|
141
|
-
# Button text (shown on hover)
|
142
|
-
config.button_text = "Buy me a coffee"
|
143
|
-
|
144
|
-
# Modal customization
|
145
|
-
config.modal_title = "Support my work"
|
146
|
-
config.modal_description = "Your support helps me continue creating."
|
147
|
-
|
148
|
-
# Tip amounts shown in modal
|
149
|
-
config.custom_amounts = [
|
150
|
-
{ amount: 5, label: "$5", default: false },
|
151
|
-
{ amount: 10, label: "$10", default: true },
|
152
|
-
{ amount: 25, label: "$25", default: false },
|
153
|
-
{ amount: 50, label: "$50", default: false }
|
154
|
-
]
|
155
|
-
|
156
|
-
# Additional styling
|
157
|
-
config.button_class = "custom-class"
|
158
|
-
config.z_index = 1000
|
159
|
-
|
160
|
-
# Analytics
|
161
|
-
config.analytics_enabled = true # Works with GA4 and Plausible
|
162
|
-
end
|
163
|
-
```
|
140
|
+
All configuration is done directly in the view helper:
|
164
141
|
|
165
|
-
|
142
|
+
### Common Options
|
166
143
|
|
167
|
-
|
144
|
+
| Option | Description | Default | Values |
|
145
|
+
|--------|-------------|---------|--------|
|
146
|
+
| `payment_link` | Single payment URL for simple mode | - | URL string |
|
147
|
+
| `payment_links` | Hash of payment URLs for modal mode | - | Hash with keys like `:small`, `:medium`, `:large` |
|
148
|
+
| `message` / `button_text` | Text shown on button (on hover) | `"Tip Jar"` | String |
|
149
|
+
| `icon` | Button icon | `:jar` | `:coffee`, `:heart`, `:star`, `:dollar`, `:jar`, or custom SVG |
|
150
|
+
| `position` | Button position on screen | `:bottom_right` | `:bottom_right`, `:bottom_left`, `:top_right`, `:top_left` |
|
151
|
+
| `color` | Button background color | `"#3b82f6"` | Hex color string |
|
152
|
+
| `text_color` | Button text color | `"#ffffff"` | Hex color string |
|
153
|
+
| `pulse` | Enable pulsing animation | `false` | `true` / `false` |
|
154
|
+
| `z_index` | CSS z-index for stacking | `1000` | Integer |
|
155
|
+
| `class` | Additional CSS classes | `""` | String |
|
156
|
+
| `use_modal` | Force modal mode | `false` | `true` / `false` |
|
168
157
|
|
169
|
-
|
170
|
-
<!-- Default button with all config options -->
|
171
|
-
<%= tipjar_button %>
|
158
|
+
### Modal-Specific Options
|
172
159
|
|
173
|
-
|
174
|
-
|
160
|
+
| Option | Description | Default |
|
161
|
+
|--------|-------------|----------|
|
162
|
+
| `modal_title` | Modal header text | `"Support my work"` |
|
163
|
+
| `modal_description` | Modal description text | `"Your support helps..."` |
|
164
|
+
| `theme` | Modal color theme | `:light` |
|
165
|
+
| `custom_amounts` | Array of amount options | See example below |
|
166
|
+
| `analytics_enabled` | Track user interactions | `false` |
|
175
167
|
|
176
|
-
|
177
|
-
|
178
|
-
```
|
168
|
+
### Custom Amounts Example
|
169
|
+
|
170
|
+
```ruby
|
171
|
+
custom_amounts: [
|
172
|
+
{ amount: 5, label: "$5", default: false },
|
173
|
+
{ amount: 10, label: "$10", default: true }, # This will be pre-selected
|
174
|
+
{ amount: 25, label: "$25", default: false },
|
175
|
+
{ amount: 50, label: "$50", default: false }
|
176
|
+
]
|
179
177
|
|
180
|
-
|
178
|
+
## Additional Helpers
|
179
|
+
|
180
|
+
### Custom Tip Links
|
181
181
|
|
182
182
|
```erb
|
183
|
-
<!-- Create a custom tip link -->
|
183
|
+
<!-- Create a custom tip link (requires initializer config) -->
|
184
184
|
<%= tipjar_link "Support this project", amount: :large %>
|
185
185
|
|
186
186
|
<!-- With custom styling -->
|
@@ -194,18 +194,30 @@ end
|
|
194
194
|
<%= tipjar_modal %>
|
195
195
|
```
|
196
196
|
|
197
|
+
## Backwards Compatibility
|
198
|
+
|
199
|
+
If you're upgrading from v0.3.0 or earlier and want to keep using the initializer-based configuration:
|
200
|
+
|
201
|
+
```erb
|
202
|
+
<!-- Use the deprecated tipjar_button helper -->
|
203
|
+
<%= tipjar_button %>
|
204
|
+
```
|
205
|
+
|
206
|
+
This requires having a `config/initializers/tipjar.rb` file. We recommend migrating to the new `tip_jar` helper with inline options for easier customization.
|
207
|
+
|
197
208
|
## Styling
|
198
209
|
|
199
210
|
As of v0.2.0, the gem is fully self-contained with inline styles - no external CSS required! The button works out of the box without any app-side styling.
|
200
211
|
|
201
212
|
### Customization Options
|
202
213
|
|
203
|
-
1. **Via
|
204
|
-
```
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
214
|
+
1. **Via Helper Options** (Recommended):
|
215
|
+
```erb
|
216
|
+
<%= tip_jar payment_link: 'https://your.link',
|
217
|
+
color: '#10b981', # Green background
|
218
|
+
text_color: '#000000', # Black text
|
219
|
+
pulse: true, # Enable pulsing animation
|
220
|
+
class: 'custom' %> # Add custom CSS classes
|
209
221
|
```
|
210
222
|
|
211
223
|
2. **Via CSS Classes** (for modal mode):
|
@@ -256,16 +268,18 @@ gem 'rails_tipjar', path: '../path/to/rails_tipjar'
|
|
256
268
|
## Icon Options
|
257
269
|
|
258
270
|
The gem includes 5 built-in icons:
|
259
|
-
- `:
|
271
|
+
- `:jar` - Tip jar with animated coin (default)
|
272
|
+
- `:coffee` - Coffee cup
|
260
273
|
- `:heart` - Heart shape
|
261
274
|
- `:star` - Star
|
262
275
|
- `:dollar` - Dollar sign in circle
|
263
|
-
- `:jar` - Tip jar with animated coin
|
264
276
|
|
265
277
|
You can also provide a custom SVG string for complete customization.
|
266
278
|
|
267
279
|
## Version History
|
268
280
|
|
281
|
+
- **v1.0.1** - Changed default button text to "Tip Jar" and default icon to jar
|
282
|
+
- **v1.0.0** - Stable release with all configuration in view helper options (no initializer needed!)
|
269
283
|
- **v0.3.0** - Made payment provider agnostic (works with any payment link service)
|
270
284
|
- **v0.2.2** - Added color customization and pulse animation control
|
271
285
|
- **v0.2.1** - Fixed button circular shape when icon only displayed
|
@@ -1,58 +1,167 @@
|
|
1
1
|
module TipjarHelper
|
2
|
+
def tip_jar(options = {})
|
3
|
+
# Extract all options with sensible defaults
|
4
|
+
payment_link = options[:payment_link] || options[:link]
|
5
|
+
payment_links = options[:payment_links]
|
6
|
+
use_modal = options[:use_modal] || false
|
7
|
+
|
8
|
+
# Button configuration
|
9
|
+
message = options[:message] || options[:button_text] || "Tip Jar"
|
10
|
+
icon = options[:icon] || :jar
|
11
|
+
position = options[:position] || :bottom_right
|
12
|
+
color = options[:color] || "#3b82f6"
|
13
|
+
text_color = options[:text_color] || "#ffffff"
|
14
|
+
pulse = options[:pulse] || false
|
15
|
+
z_index = options[:z_index] || 1000
|
16
|
+
custom_class = options[:class] || ""
|
17
|
+
|
18
|
+
# Modal configuration (if using modal)
|
19
|
+
modal_title = options[:modal_title] || "Support my work"
|
20
|
+
modal_description = options[:modal_description] || "Your support helps me continue creating and maintaining this project."
|
21
|
+
theme = options[:theme] || :light
|
22
|
+
custom_amounts = options[:custom_amounts] || [
|
23
|
+
{ amount: 5, label: "$5", default: false },
|
24
|
+
{ amount: 10, label: "$10", default: true },
|
25
|
+
{ amount: 25, label: "$25", default: false },
|
26
|
+
{ amount: 50, label: "$50", default: false }
|
27
|
+
]
|
28
|
+
analytics_enabled = options[:analytics_enabled] || false
|
29
|
+
|
30
|
+
# Ensure color has # prefix
|
31
|
+
color = "##{color}" unless color.start_with?('#')
|
32
|
+
text_color = "##{text_color}" unless text_color.start_with?('#')
|
33
|
+
|
34
|
+
# If payment_links is provided or use_modal is true, use modal mode
|
35
|
+
if payment_links || use_modal
|
36
|
+
# Modal mode
|
37
|
+
tipjar_modal_button(
|
38
|
+
payment_links: payment_links || { default: payment_link },
|
39
|
+
position: position,
|
40
|
+
icon: icon,
|
41
|
+
theme: theme,
|
42
|
+
button_text: message,
|
43
|
+
modal_title: modal_title,
|
44
|
+
modal_description: modal_description,
|
45
|
+
custom_amounts: custom_amounts,
|
46
|
+
button_class: custom_class,
|
47
|
+
z_index: z_index,
|
48
|
+
analytics_enabled: analytics_enabled,
|
49
|
+
color: color,
|
50
|
+
text_color: text_color,
|
51
|
+
pulse: pulse
|
52
|
+
)
|
53
|
+
elsif payment_link
|
54
|
+
# Simple direct link mode
|
55
|
+
tipjar_simple_button(
|
56
|
+
payment_link: payment_link,
|
57
|
+
message: message,
|
58
|
+
icon: icon,
|
59
|
+
position: position,
|
60
|
+
color: color,
|
61
|
+
text_color: text_color,
|
62
|
+
pulse: pulse,
|
63
|
+
z_index: z_index,
|
64
|
+
custom_class: custom_class
|
65
|
+
)
|
66
|
+
else
|
67
|
+
# No payment method specified
|
68
|
+
raise ArgumentError, "You must provide either :payment_link or :payment_links option to tip_jar helper"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Deprecated - kept for backwards compatibility
|
2
73
|
def tipjar_button(options = {})
|
3
|
-
config = RailsTipjar.config
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
74
|
+
config = RailsTipjar.config if defined?(RailsTipjar)
|
75
|
+
|
76
|
+
if config && (config.payment_link || config.payment_links.any?)
|
77
|
+
# Use config from initializer for backwards compatibility
|
78
|
+
tip_jar(
|
79
|
+
payment_link: config.payment_link,
|
80
|
+
payment_links: config.payment_links.any? ? config.payment_links : nil,
|
81
|
+
use_modal: config.use_modal,
|
82
|
+
position: options[:position] || config.position,
|
83
|
+
icon: config.icon,
|
84
|
+
button_text: config.button_text,
|
85
|
+
color: config.color,
|
86
|
+
text_color: config.text_color,
|
87
|
+
pulse: config.pulse,
|
88
|
+
z_index: options[:z_index] || config.z_index,
|
89
|
+
class: options[:class] || config.button_class,
|
90
|
+
modal_title: config.modal_title,
|
91
|
+
modal_description: config.modal_description,
|
92
|
+
custom_amounts: config.custom_amounts,
|
93
|
+
theme: config.theme,
|
94
|
+
analytics_enabled: config.analytics_enabled
|
95
|
+
)
|
96
|
+
else
|
97
|
+
raise ArgumentError, "tipjar_button requires configuration. Use tip_jar helper with options instead."
|
98
|
+
end
|
11
99
|
end
|
12
100
|
|
13
101
|
private
|
14
102
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
103
|
+
def tipjar_simple_button(options = {})
|
104
|
+
payment_link = options[:payment_link]
|
105
|
+
message = options[:message]
|
106
|
+
icon = options[:icon]
|
107
|
+
position = options[:position]
|
108
|
+
color = options[:color]
|
109
|
+
text_color = options[:text_color]
|
110
|
+
pulse = options[:pulse]
|
111
|
+
z_index = options[:z_index]
|
112
|
+
custom_class = options[:custom_class]
|
113
|
+
|
114
|
+
position_style = position_inline_styles(position)
|
115
|
+
animation_style = pulse ? "animation: tipjar-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;" : ""
|
116
|
+
|
117
|
+
# Default to collapsed (icon-only) that expands on hover - 48x48px total
|
118
|
+
button_style = "#{position_style} z-index: #{z_index}; display: inline-flex; align-items: center; justify-content: center; padding: 12px; background-color: #{color}; color: #{text_color}; border-radius: 9999px; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); transition: all 0.3s ease; cursor: pointer; border: none; font-size: 0.875rem; font-weight: 500; text-decoration: none; box-sizing: border-box; #{animation_style}"
|
119
|
+
|
120
|
+
hover_color = darken_color(color)
|
121
|
+
|
122
|
+
# Inject styles if needed
|
123
|
+
styles = tipjar_styles
|
124
|
+
|
125
|
+
# Create the link with inline styles - collapsed by default, expands on hover
|
126
|
+
link_html = link_to payment_link,
|
127
|
+
target: "_blank",
|
128
|
+
rel: "noopener",
|
129
|
+
class: "tipjar-button #{custom_class}",
|
130
|
+
style: button_style,
|
131
|
+
onmouseover: "this.style.backgroundColor='#{hover_color}'; this.style.transform='scale(1.05)'; this.style.padding='12px 20px'; this.querySelector('.tipjar-text').style.maxWidth='200px'; this.querySelector('.tipjar-text').style.marginLeft='0.5rem';",
|
132
|
+
onmouseout: "this.style.backgroundColor='#{color}'; this.style.transform='scale(1)'; this.style.padding='12px'; this.querySelector('.tipjar-text').style.maxWidth='0'; this.querySelector('.tipjar-text').style.marginLeft='0';" do
|
133
|
+
content_tag(:span, style: "display: inline-flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem;") do
|
134
|
+
raw icon_svg(icon)
|
135
|
+
end +
|
136
|
+
content_tag(:span, message, class: "tipjar-text", style: "white-space: nowrap; max-width: 0; overflow: hidden; transition: all 0.3s ease; margin-left: 0;")
|
137
|
+
end
|
138
|
+
|
139
|
+
styles + link_html
|
140
|
+
end
|
141
|
+
|
142
|
+
def tipjar_modal_button(options = {})
|
143
|
+
# Modal mode - renders button with modal
|
144
|
+
content_tag :div,
|
145
|
+
class: "tipjar-container",
|
146
|
+
data: {
|
147
|
+
controller: "tipjar",
|
148
|
+
tipjar_payment_links_value: options[:payment_links].to_json,
|
149
|
+
tipjar_theme_value: options[:theme],
|
150
|
+
tipjar_modal_title_value: options[:modal_title],
|
151
|
+
tipjar_modal_description_value: options[:modal_description],
|
152
|
+
tipjar_custom_amounts_value: options[:custom_amounts].to_json,
|
153
|
+
tipjar_analytics_enabled_value: options[:analytics_enabled]
|
154
|
+
} do
|
155
|
+
render partial: "tipjar/button", locals: {
|
156
|
+
position: options[:position],
|
157
|
+
custom_class: options[:button_class],
|
158
|
+
z_index: options[:z_index],
|
159
|
+
icon: options[:icon],
|
160
|
+
button_text: options[:button_text],
|
161
|
+
color: options[:color],
|
162
|
+
text_color: options[:text_color],
|
163
|
+
pulse: options[:pulse]
|
164
|
+
}
|
56
165
|
end
|
57
166
|
end
|
58
167
|
|
@@ -133,6 +242,128 @@ module TipjarHelper
|
|
133
242
|
end
|
134
243
|
end
|
135
244
|
|
245
|
+
def icon_svg(icon)
|
246
|
+
case icon
|
247
|
+
when :coffee
|
248
|
+
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
249
|
+
<defs>
|
250
|
+
<style>
|
251
|
+
@keyframes steam1 {
|
252
|
+
0% { opacity: 0; transform: translateY(0) translateX(0); }
|
253
|
+
20% { opacity: 0.8; }
|
254
|
+
50% { opacity: 0.6; transform: translateY(-3px) translateX(1px); }
|
255
|
+
80% { opacity: 0.3; }
|
256
|
+
100% { opacity: 0; transform: translateY(-8px) translateX(-1px); }
|
257
|
+
}
|
258
|
+
@keyframes steam2 {
|
259
|
+
0% { opacity: 0; transform: translateY(0) translateX(0); }
|
260
|
+
15% { opacity: 0.7; }
|
261
|
+
45% { opacity: 0.5; transform: translateY(-4px) translateX(-1px); }
|
262
|
+
75% { opacity: 0.2; }
|
263
|
+
100% { opacity: 0; transform: translateY(-9px) translateX(1px); }
|
264
|
+
}
|
265
|
+
@keyframes steam3 {
|
266
|
+
0% { opacity: 0; transform: translateY(0) translateX(0); }
|
267
|
+
25% { opacity: 0.6; }
|
268
|
+
55% { opacity: 0.4; transform: translateY(-3px) translateX(0.5px); }
|
269
|
+
85% { opacity: 0.1; }
|
270
|
+
100% { opacity: 0; transform: translateY(-7px) translateX(-0.5px); }
|
271
|
+
}
|
272
|
+
.steam1 { animation: steam1 3s ease-out infinite; }
|
273
|
+
.steam2 { animation: steam2 3s ease-out infinite 0.5s; }
|
274
|
+
.steam3 { animation: steam3 3s ease-out infinite 1s; }
|
275
|
+
</style>
|
276
|
+
</defs>
|
277
|
+
<!-- Steam wisps with wavy paths -->
|
278
|
+
<path class="steam1" d="M8 9c0.5-0.5 0.5-1 0-1.5s-0.5-1 0-1.5s0.5-1 0-1.5" stroke-linecap="round" fill="none" opacity="0"/>
|
279
|
+
<path class="steam2" d="M12 8.5c-0.3-0.4 -0.3-0.8 0-1.2s0.3-0.8 0-1.2s-0.3-0.8 0-1.2" stroke-linecap="round" fill="none" opacity="0"/>
|
280
|
+
<path class="steam3" d="M15.5 9c0.4-0.3 0.4-0.7 0-1s-0.4-0.7 0-1s0.4-0.7 0-1" stroke-linecap="round" fill="none" opacity="0"/>
|
281
|
+
<!-- Coffee cup body -->
|
282
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M6 10h12v7a3 3 0 01-3 3H9a3 3 0 01-3-3v-7z"/>
|
283
|
+
<!-- Cup handle -->
|
284
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M18 10h1.5a2.5 2.5 0 010 5H18"/>
|
285
|
+
<!-- Saucer -->
|
286
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M4 20h16"/>
|
287
|
+
<!-- Coffee surface detail -->
|
288
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M8 12h8" opacity="0.3"/>
|
289
|
+
</svg>'
|
290
|
+
when :heart
|
291
|
+
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
292
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M21 8.5c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 4 3 6.015 3 8.5c0 7.5 9 11.5 9 11.5s9-4 9-11.5z" />
|
293
|
+
</svg>'
|
294
|
+
when :star
|
295
|
+
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
296
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z" />
|
297
|
+
</svg>'
|
298
|
+
when :dollar
|
299
|
+
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
300
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v12m-3-2.818l.879.659c1.171.879 3.07.879 4.242 0 1.172-.879 1.172-2.303 0-3.182C13.536 12.219 12.768 12 12 12c-.725 0-1.45-.22-2.003-.659-1.106-.879-1.106-2.303 0-3.182s2.9-.879 4.006 0l.415.33M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
301
|
+
</svg>'
|
302
|
+
when :jar
|
303
|
+
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
304
|
+
<defs>
|
305
|
+
<style>
|
306
|
+
@keyframes tipjar-coin-drop-new {
|
307
|
+
0% {
|
308
|
+
transform: translateY(0px);
|
309
|
+
opacity: 0;
|
310
|
+
}
|
311
|
+
10% {
|
312
|
+
opacity: 1;
|
313
|
+
transform: translateY(2px);
|
314
|
+
}
|
315
|
+
30% {
|
316
|
+
transform: translateY(6px);
|
317
|
+
}
|
318
|
+
50% {
|
319
|
+
transform: translateY(10px);
|
320
|
+
opacity: 1;
|
321
|
+
}
|
322
|
+
70% {
|
323
|
+
transform: translateY(15.5px);
|
324
|
+
opacity: 1;
|
325
|
+
}
|
326
|
+
75% {
|
327
|
+
transform: translateY(16.3px);
|
328
|
+
opacity: 1;
|
329
|
+
}
|
330
|
+
80% {
|
331
|
+
transform: translateY(15.8px);
|
332
|
+
opacity: 0.8;
|
333
|
+
}
|
334
|
+
100% {
|
335
|
+
transform: translateY(16.3px);
|
336
|
+
opacity: 0;
|
337
|
+
}
|
338
|
+
}
|
339
|
+
.tipjar-coin-drop-new {
|
340
|
+
animation: tipjar-coin-drop-new 2.5s ease-in-out infinite;
|
341
|
+
}
|
342
|
+
</style>
|
343
|
+
</defs>
|
344
|
+
<!-- Jar lid -->
|
345
|
+
<rect x="9.5" y="3" width="5" height="1" rx="0.25" stroke-linecap="round" stroke-linejoin="round"/>
|
346
|
+
<!-- Jar threads/neck -->
|
347
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M10 4v0.8M14 4v0.8"/>
|
348
|
+
<!-- Jar body - much fatter with short taper -->
|
349
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M10 4.8h4M9 5.5c-1 0 -2 0.5 -2 1v12.5a2 2 0 002 2h6a2 2 0 002-2V6.5c0-0.5 -1-1 -2-1"/>
|
350
|
+
<!-- Coins at bottom - pile -->
|
351
|
+
<ellipse cx="10.5" cy="18.5" rx="1.5" ry="0.5" stroke-linecap="round"/>
|
352
|
+
<ellipse cx="13.5" cy="18.3" rx="1.5" ry="0.5" stroke-linecap="round"/>
|
353
|
+
<ellipse cx="12" cy="17.8" rx="1.5" ry="0.5" stroke-linecap="round"/>
|
354
|
+
<ellipse cx="11" cy="19" rx="1.3" ry="0.4" stroke-linecap="round"/>
|
355
|
+
<ellipse cx="13" cy="19" rx="1.3" ry="0.4" stroke-linecap="round"/>
|
356
|
+
<!-- Falling coin - starts above jar outside -->
|
357
|
+
<g class="tipjar-coin-drop-new">
|
358
|
+
<ellipse cx="12" cy="1.5" rx="1.5" ry="0.5" stroke-linecap="round"/>
|
359
|
+
</g>
|
360
|
+
</svg>'
|
361
|
+
else
|
362
|
+
# Allow custom SVG string
|
363
|
+
icon.to_s
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
136
367
|
def darken_color(hex_color)
|
137
368
|
# Remove # if present
|
138
369
|
hex = hex_color.gsub('#', '')
|
@@ -2,15 +2,15 @@
|
|
2
2
|
data-tipjar-target="button"
|
3
3
|
data-action="click->tipjar#openModal"
|
4
4
|
class="tipjar-button <%= config_position_classes(position) %> <%= custom_class %>"
|
5
|
-
style="z-index: <%= z_index %>;"
|
6
|
-
aria-label="<%=
|
5
|
+
style="z-index: <%= z_index %>; background-color: <%= color %>; color: <%= text_color %>; <%= pulse ? 'animation: tipjar-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;' : '' %>"
|
6
|
+
aria-label="<%= button_text %>"
|
7
7
|
>
|
8
8
|
<span class="tipjar-button-icon">
|
9
|
-
<%= raw
|
9
|
+
<%= raw icon_svg(icon) %>
|
10
10
|
</span>
|
11
11
|
<span class="tipjar-button-text">
|
12
|
-
<%=
|
12
|
+
<%= button_text %>
|
13
13
|
</span>
|
14
14
|
</button>
|
15
15
|
|
16
|
-
<%= render "tipjar/modal",
|
16
|
+
<%= render "tipjar/modal", locals: local_assigns.except(:position, :custom_class, :z_index, :icon, :button_text, :color, :text_color, :pulse) %>
|
@@ -5,10 +5,12 @@ module Tipjar
|
|
5
5
|
class InstallGenerator < Rails::Generators::Base
|
6
6
|
source_root File.expand_path("templates", __dir__)
|
7
7
|
|
8
|
-
desc "Creates
|
8
|
+
desc "Creates an optional RailsTipjar initializer for backwards compatibility"
|
9
9
|
|
10
10
|
def copy_initializer
|
11
|
-
|
11
|
+
if yes?("Do you want to create an initializer file for backwards compatibility? (not recommended - use view helper options instead) [y/N]")
|
12
|
+
template "tipjar.rb", "config/initializers/tipjar.rb"
|
13
|
+
end
|
12
14
|
end
|
13
15
|
|
14
16
|
def add_stimulus_controller
|
@@ -69,26 +71,31 @@ module Tipjar
|
|
69
71
|
say "\n"
|
70
72
|
say "Next steps:", :yellow
|
71
73
|
say "1. Create payment links with your preferred provider (Stripe, PayPal, Ko-fi, etc.)", :yellow
|
72
|
-
say "2.
|
73
|
-
say "3. Add <%= tipjar_button %> to your layout file", :yellow
|
74
|
+
say "2. Add the tip jar to your views using the helper", :yellow
|
74
75
|
say "\n"
|
75
|
-
say "Example
|
76
|
-
say <<~
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
76
|
+
say "Example usage in your views:", :cyan
|
77
|
+
say <<~USAGE
|
78
|
+
<!-- Simple button with direct link -->
|
79
|
+
<%= tip_jar payment_link: 'https://your.payment.link' %>
|
80
|
+
|
81
|
+
<!-- With custom options -->
|
82
|
+
<%= tip_jar payment_link: 'https://your.payment.link',
|
83
|
+
message: 'Support This Project',
|
84
|
+
icon: :heart,
|
85
|
+
color: '#8b5cf6',
|
86
|
+
pulse: true %>
|
87
|
+
|
88
|
+
<!-- Modal with multiple payment amounts -->
|
89
|
+
<%= tip_jar payment_links: {
|
90
|
+
small: 'https://link-5',
|
91
|
+
medium: 'https://link-10',
|
92
|
+
large: 'https://link-25'
|
93
|
+
},
|
94
|
+
modal_title: 'Support my work',
|
95
|
+
position: :bottom_left %>
|
96
|
+
USAGE
|
97
|
+
say "\n"
|
98
|
+
say "For more options, see the README: https://github.com/justinpaulson/rails_tipjar", :cyan
|
92
99
|
say "\n"
|
93
100
|
end
|
94
101
|
end
|
@@ -13,9 +13,9 @@ module RailsTipjar
|
|
13
13
|
# Legacy modal mode
|
14
14
|
@payment_links = {}
|
15
15
|
@position = :bottom_right
|
16
|
-
@icon = :
|
16
|
+
@icon = :jar
|
17
17
|
@theme = :light
|
18
|
-
@button_text = "
|
18
|
+
@button_text = "Tip Jar"
|
19
19
|
@modal_title = "Support my work"
|
20
20
|
@modal_description = "Your support helps me continue creating and maintaining this project."
|
21
21
|
@custom_amounts = [
|
data/lib/rails_tipjar/version.rb
CHANGED