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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0dad170082ce372bad125b49719b0cffb1e6b81575161042feb724d33e5ab8d6
4
- data.tar.gz: 6db6495061f0f76370133fd8a31f32e6c0610df1155309aef0f2ef50b3eb5c24
3
+ metadata.gz: 2acacf788da12d40f7f2b20ae9042e0adf416bb17475c20cd309a737120143fa
4
+ data.tar.gz: ed97fb19a2935a38bc26c29c86be548c1d33a08c33081dfc336e88af83957a36
5
5
  SHA512:
6
- metadata.gz: c20a0b31e0f00b467b392fff0884fadd941f0704a52c140db0fc52e9fdb2d682190cabbb74a985fa0fee6b805c0c38182d3f9aa67aaed1edfadabc6273897371
7
- data.tar.gz: 4d557ecd1a09c866de21acff09aa98b40be0545a03eb8c1abc23db17a3ca363a0a2b740023796497630acd6c40c8877ca3af7a03d09551fe0a9895476ad60155
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. Configure the Gem
67
+ ### 2. Add to Your Views
64
68
 
65
- Edit `config/initializers/tipjar.rb`:
69
+ No configuration file needed! Simply use the helper in your views with all options:
66
70
 
67
- ```ruby
68
- RailsTipjar.configure do |config|
69
- # Simple mode: just one link (no modal)
70
- config.payment_link = "https://your-payment-provider.com/your-link"
71
-
72
- # Or use modal mode with multiple amounts
73
- config.payment_links = {
74
- small: "https://your-provider.com/tip-5",
75
- medium: "https://your-provider.com/tip-10",
76
- large: "https://your-provider.com/tip-25"
77
- }
78
-
79
- config.position = :bottom_right
80
- config.icon = :coffee
81
- config.button_text = "Buy me a coffee"
82
- end
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
- ### 3. Add to Your Layout
91
+ #### Modal Mode (Multiple Payment Options)
86
92
 
87
- In `app/views/layouts/application.html.erb`:
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
- <%= tipjar_button %>
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
- ## Configuration Options
138
+ ## Helper Options
107
139
 
108
- ```ruby
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
- ## Usage
142
+ ### Common Options
166
143
 
167
- ### Basic Button
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
- ```erb
170
- <!-- Default button with all config options -->
171
- <%= tipjar_button %>
158
+ ### Modal-Specific Options
172
159
 
173
- <!-- Override position for specific button -->
174
- <%= tipjar_button position: :top_left %>
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
- <!-- Add custom CSS classes -->
177
- <%= tipjar_button class: "my-custom-class" %>
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
- ### Custom Links
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 Configuration** (Recommended):
204
- ```ruby
205
- config.color = "#10b981" # Green background
206
- config.text_color = "#000000" # Black text
207
- config.pulse = true # Enable pulsing animation
208
- config.button_class = "custom" # Add custom CSS classes
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
- - `:coffee` - Coffee cup (default)
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
- position = options[:position] || config.position
6
- custom_class = options[:class] || config.button_class
7
- z_index = options[:z_index] || config.z_index
8
-
9
- # Inject CSS styles into the page once
10
- tipjar_styles + tipjar_button_html(config, position, custom_class, z_index)
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 tipjar_button_html(config, position, custom_class, z_index)
16
- # Simple direct link mode when payment_link is set
17
- if config.payment_link && !config.use_modal
18
- position_style = position_inline_styles(position)
19
- animation_style = config.pulse ? "animation: tipjar-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;" : ""
20
- button_style = "#{position_style} z-index: #{z_index}; display: flex; align-items: center; padding: 0.75rem; background-color: #{config.color}; color: #{config.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; #{animation_style}"
21
-
22
- hover_color = darken_color(config.color)
23
-
24
- link_to config.payment_link,
25
- target: "_blank",
26
- rel: "noopener",
27
- class: "tipjar-button #{custom_class}",
28
- style: button_style,
29
- onmouseover: "this.style.backgroundColor='#{hover_color}'; this.style.transform='scale(1.05)'; this.querySelector('.tipjar-button-text').style.maxWidth='200px'; this.querySelector('.tipjar-button-text').style.marginLeft='0.5rem';",
30
- onmouseout: "this.style.backgroundColor='#{config.color}'; this.style.transform='scale(1)'; this.querySelector('.tipjar-button-text').style.maxWidth='0'; this.querySelector('.tipjar-button-text').style.marginLeft='0';" do
31
- content_tag(:span, style: "display: flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem;") do
32
- raw config.icon_svg
33
- end +
34
- content_tag(:span, config.button_text, class: "tipjar-button-text", style: "white-space: nowrap; max-width: 0; overflow: hidden; transition: all 0.3s ease; margin-left: 0;")
35
- end
36
- else
37
- # Original modal mode - would need more work to be fully inline
38
- content_tag :div,
39
- class: "tipjar-container",
40
- data: {
41
- controller: "tipjar",
42
- tipjar_payment_links_value: config.payment_links.to_json,
43
- tipjar_theme_value: config.theme,
44
- tipjar_modal_title_value: config.modal_title,
45
- tipjar_modal_description_value: config.modal_description,
46
- tipjar_custom_amounts_value: config.custom_amounts.to_json,
47
- tipjar_analytics_enabled_value: config.analytics_enabled
48
- } do
49
- render partial: "tipjar/button", locals: {
50
- position: position,
51
- custom_class: custom_class,
52
- z_index: z_index,
53
- config: config
54
- }
55
- end
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="<%= config.button_text %>"
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 config.icon_svg %>
9
+ <%= raw icon_svg(icon) %>
10
10
  </span>
11
11
  <span class="tipjar-button-text">
12
- <%= config.button_text %>
12
+ <%= button_text %>
13
13
  </span>
14
14
  </button>
15
15
 
16
- <%= render "tipjar/modal", config: config %>
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 a RailsTipjar initializer and copies necessary files"
8
+ desc "Creates an optional RailsTipjar initializer for backwards compatibility"
9
9
 
10
10
  def copy_initializer
11
- template "tipjar.rb", "config/initializers/tipjar.rb"
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. Configure your payment links in config/initializers/tipjar.rb", :yellow
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 configuration:", :cyan
76
- say <<~CONFIG
77
- RailsTipjar.configure do |config|
78
- # Simple mode - just one link:
79
- config.payment_link = "https://your-payment-provider.com/tip"
80
-
81
- # Or modal mode with multiple amounts:
82
- config.payment_links = {
83
- small: "https://your-provider.com/tip-5",
84
- medium: "https://your-provider.com/tip-10",
85
- large: "https://your-provider.com/tip-25"
86
- }
87
- config.position = :bottom_right
88
- config.icon = :coffee
89
- config.theme = :light
90
- end
91
- CONFIG
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 = :coffee
16
+ @icon = :jar
17
17
  @theme = :light
18
- @button_text = "Buy me a coffee"
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 = [
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsTipjar
4
- VERSION = "0.3.0"
4
+ VERSION = "1.0.1"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_tipjar
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Paulson