wilday_ui 0.5.6 → 0.7.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.
- checksums.yaml +4 -4
- data/README.md +7 -0
- data/app/assets/builds/wilday_ui/index.js +223 -0
- data/app/assets/builds/wilday_ui/index.js.map +3 -3
- data/app/assets/stylesheets/wilday_ui/components/button/features/clipboard.css +108 -0
- data/app/assets/stylesheets/wilday_ui/components/button/features/confirmation.css +136 -0
- data/app/assets/stylesheets/wilday_ui/components/button/features/gradients.css +109 -0
- data/app/assets/stylesheets/wilday_ui/components/button/features/variants.css +5 -0
- data/app/assets/stylesheets/wilday_ui/components/button/index.css +4 -0
- data/app/assets/stylesheets/wilday_ui/tokens/colors.css +109 -0
- data/app/helpers/wilday_ui/application_helper.rb +1 -0
- data/app/helpers/wilday_ui/components/button_helper.rb +170 -20
- data/app/helpers/wilday_ui/theme_helper.rb +19 -0
- data/app/javascript/wilday_ui/controllers/clipboard_controller.js +76 -0
- data/app/javascript/wilday_ui/controllers/confirmation_controller.js +216 -0
- data/app/javascript/wilday_ui/controllers/index.js +4 -1
- data/app/views/wilday_ui/_button.html.erb +1 -0
- data/lib/wilday_ui/config/theme.rb +6 -6
- data/lib/wilday_ui/version.rb +1 -1
- metadata +9 -2
@@ -11,6 +11,16 @@ module WildayUi
|
|
11
11
|
wrapper_required: false,
|
12
12
|
stimulus_controller: "button",
|
13
13
|
default_stimulus_action: "click->button#toggleLoading"
|
14
|
+
},
|
15
|
+
copy_to_clipboard: {
|
16
|
+
wrapper_required: true,
|
17
|
+
stimulus_controller: "clipboard button",
|
18
|
+
default_stimulus_action: "click->clipboard#copy click->button#toggleLoading"
|
19
|
+
},
|
20
|
+
confirm: {
|
21
|
+
wrapper_required: true,
|
22
|
+
stimulus_controller: "confirmation",
|
23
|
+
default_stimulus_action: "click->confirmation#showDialog"
|
14
24
|
}
|
15
25
|
# Add more features here as needed
|
16
26
|
# tooltip: {
|
@@ -25,6 +35,7 @@ module WildayUi
|
|
25
35
|
variant: :solid,
|
26
36
|
size: :medium,
|
27
37
|
radius: :rounded,
|
38
|
+
gradient: nil,
|
28
39
|
icon: nil,
|
29
40
|
icon_position: :left,
|
30
41
|
icon_only: false,
|
@@ -41,6 +52,8 @@ module WildayUi
|
|
41
52
|
dropdown_items: nil,
|
42
53
|
dropdown_icon: nil,
|
43
54
|
theme: nil,
|
55
|
+
copy_to_clipboard: nil,
|
56
|
+
confirm: nil,
|
44
57
|
**options
|
45
58
|
)
|
46
59
|
content_for(:head) { stylesheet_link_tag "wilday_ui/components/button/index", media: "all" }
|
@@ -49,6 +62,12 @@ module WildayUi
|
|
49
62
|
wrapper_data = {}
|
50
63
|
wrapper_options = nil
|
51
64
|
|
65
|
+
# Process gradient styles if present
|
66
|
+
if gradient.present?
|
67
|
+
gradient_styles = process_gradient(gradient)
|
68
|
+
options[:style] = [ options[:style], gradient_styles ].compact.join(";") if gradient_styles.present?
|
69
|
+
end
|
70
|
+
|
52
71
|
# Process theme styles
|
53
72
|
if theme.present?
|
54
73
|
theme_styles = process_theme(variant, theme)
|
@@ -58,17 +77,13 @@ module WildayUi
|
|
58
77
|
variant_class = get_variant_class(variant)
|
59
78
|
size_class = get_size_class(size)
|
60
79
|
radius_class = get_radius_class(radius)
|
80
|
+
gradient_class = get_gradient_class(gradient)
|
61
81
|
|
62
82
|
# Setup features that require Stimulus controllers
|
63
|
-
active_features = determine_active_features(loading, dropdown, loading_text, use_default_controller)
|
64
|
-
|
65
|
-
Rails.logger.debug "Active Features: #{active_features.inspect}"
|
66
|
-
Rails.logger.debug "Options before setup: #{options.inspect}"
|
83
|
+
active_features = determine_active_features(loading, dropdown, loading_text, copy_to_clipboard, confirm, use_default_controller)
|
67
84
|
|
68
85
|
setup_features(active_features, options, use_default_controller, loading_text)
|
69
86
|
|
70
|
-
Rails.logger.debug "Options after setup: #{options.inspect}"
|
71
|
-
|
72
87
|
setup_link_options(options, href, target, method)
|
73
88
|
|
74
89
|
if dropdown
|
@@ -81,6 +96,24 @@ module WildayUi
|
|
81
96
|
)
|
82
97
|
end
|
83
98
|
|
99
|
+
if copy_to_clipboard
|
100
|
+
setup_clipboard_options(
|
101
|
+
options,
|
102
|
+
additional_classes,
|
103
|
+
copy_to_clipboard,
|
104
|
+
wrapper_data
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
if confirm
|
109
|
+
setup_confirmation_options(
|
110
|
+
options,
|
111
|
+
additional_classes,
|
112
|
+
confirm,
|
113
|
+
wrapper_data
|
114
|
+
)
|
115
|
+
end
|
116
|
+
|
84
117
|
# Setup wrapper options if any feature requires it
|
85
118
|
wrapper_options = setup_wrapper_options(
|
86
119
|
active_features,
|
@@ -93,6 +126,7 @@ module WildayUi
|
|
93
126
|
variant_class,
|
94
127
|
size_class,
|
95
128
|
radius_class,
|
129
|
+
gradient_class,
|
96
130
|
icon,
|
97
131
|
icon_position,
|
98
132
|
icon_only,
|
@@ -147,6 +181,26 @@ module WildayUi
|
|
147
181
|
}[radius] || "w-button-rounded"
|
148
182
|
end
|
149
183
|
|
184
|
+
def get_gradient_class(gradient)
|
185
|
+
return nil unless gradient
|
186
|
+
|
187
|
+
if gradient.is_a?(Hash) && gradient[:from] && gradient[:to]
|
188
|
+
"w-button-gradient-custom"
|
189
|
+
else
|
190
|
+
"w-button-gradient-#{gradient}"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def process_gradient(gradient)
|
195
|
+
return nil unless gradient.is_a?(Hash) && gradient[:from] && gradient[:to]
|
196
|
+
|
197
|
+
if gradient[:via]
|
198
|
+
"background: linear-gradient(135deg, #{gradient[:from]}, #{gradient[:via]}, #{gradient[:to]})"
|
199
|
+
else
|
200
|
+
"background: linear-gradient(135deg, #{gradient[:from]}, #{gradient[:to]})"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
150
204
|
def process_theme(variant, theme)
|
151
205
|
return nil unless theme[:name] || theme[:custom]
|
152
206
|
|
@@ -180,36 +234,43 @@ module WildayUi
|
|
180
234
|
{
|
181
235
|
"--w-button-color": "#FFFFFF",
|
182
236
|
"--w-button-bg": colors["500"],
|
183
|
-
"--w-button-hover-bg": colors["600"]
|
237
|
+
"--w-button-hover-bg": colors["600"],
|
238
|
+
"--w-button-active-bg": colors["700"]
|
184
239
|
}
|
185
240
|
when :subtle
|
186
241
|
{
|
187
|
-
"--w-button-color": colors["
|
242
|
+
"--w-button-color": colors["700"],
|
188
243
|
"--w-button-bg": colors["50"],
|
189
|
-
"--w-button-hover-bg": colors["100"]
|
244
|
+
"--w-button-hover-bg": colors["100"],
|
245
|
+
"--w-button-hover-color": colors["800"]
|
190
246
|
}
|
191
247
|
when :surface
|
192
248
|
{
|
193
|
-
"--w-button-color": colors["
|
249
|
+
"--w-button-color": colors["700"],
|
194
250
|
"--w-button-bg": colors["50"],
|
195
251
|
"--w-button-hover-bg": colors["100"],
|
196
|
-
"--w-button-border": colors["
|
252
|
+
"--w-button-border": colors["200"],
|
253
|
+
"--w-button-hover-border": colors["300"]
|
197
254
|
}
|
198
255
|
when :outline
|
199
256
|
{
|
200
|
-
"--w-button-color": colors["
|
201
|
-
"--w-button-border": colors["
|
202
|
-
"--w-button-hover-bg": colors["50"]
|
257
|
+
"--w-button-color": colors["600"],
|
258
|
+
"--w-button-border": colors["300"],
|
259
|
+
"--w-button-hover-bg": colors["50"],
|
260
|
+
"--w-button-hover-border": colors["400"],
|
261
|
+
"--w-button-hover-color": colors["700"]
|
203
262
|
}
|
204
263
|
when :ghost
|
205
264
|
{
|
206
|
-
"--w-button-color": colors["
|
207
|
-
"--w-button-hover-bg": colors["50"]
|
265
|
+
"--w-button-color": colors["600"],
|
266
|
+
"--w-button-hover-bg": colors["50"],
|
267
|
+
"--w-button-hover-color": colors["700"]
|
208
268
|
}
|
209
269
|
when :plain
|
210
270
|
{
|
211
|
-
"--w-button-color": colors["
|
212
|
-
"--w-button-hover-color": colors["
|
271
|
+
"--w-button-color": colors["600"],
|
272
|
+
"--w-button-hover-color": colors["700"],
|
273
|
+
"--w-button-active-color": colors["800"]
|
213
274
|
}
|
214
275
|
else
|
215
276
|
{}
|
@@ -236,10 +297,12 @@ module WildayUi
|
|
236
297
|
styles.map { |k, v| "#{k}: #{v}" }.join(";")
|
237
298
|
end
|
238
299
|
|
239
|
-
def determine_active_features(loading, dropdown, loading_text = nil, use_default_controller = true)
|
300
|
+
def determine_active_features(loading, dropdown, loading_text = nil, copy_to_clipboard = nil, confirm = nil, use_default_controller = true)
|
240
301
|
features = {}
|
241
302
|
features[:loading] = true if (loading || loading_text.present?) && use_default_controller
|
242
303
|
features[:dropdown] = true if dropdown && use_default_controller
|
304
|
+
features[:copy_to_clipboard] = true if copy_to_clipboard.present? && use_default_controller
|
305
|
+
features[:confirm] = true if confirm.present? && use_default_controller
|
243
306
|
features
|
244
307
|
end
|
245
308
|
|
@@ -358,7 +421,93 @@ module WildayUi
|
|
358
421
|
"#{base}#{index}"
|
359
422
|
end
|
360
423
|
|
361
|
-
def
|
424
|
+
def setup_clipboard_options(options, additional_classes, copy_to_clipboard, wrapper_data)
|
425
|
+
return unless copy_to_clipboard.present?
|
426
|
+
|
427
|
+
clipboard_config = normalize_clipboard_options(copy_to_clipboard)
|
428
|
+
|
429
|
+
wrapper_data.merge!(
|
430
|
+
controller: "clipboard button",
|
431
|
+
clipboard_text_value: clipboard_config[:text],
|
432
|
+
clipboard_feedback_text_value: clipboard_config[:feedback_text],
|
433
|
+
clipboard_feedback_position_value: clipboard_config[:position],
|
434
|
+
clipboard_feedback_duration_value: clipboard_config[:duration]
|
435
|
+
)
|
436
|
+
|
437
|
+
options[:data][:clipboard_target] = "button"
|
438
|
+
options[:data][:button_target] = "button"
|
439
|
+
end
|
440
|
+
|
441
|
+
def normalize_clipboard_options(options)
|
442
|
+
if options.is_a?(Hash)
|
443
|
+
{
|
444
|
+
text: options[:text],
|
445
|
+
feedback_text: options[:feedback_text] || "Copied!",
|
446
|
+
position: options[:position] || "top",
|
447
|
+
duration: options[:duration] || 2000
|
448
|
+
}
|
449
|
+
else
|
450
|
+
{
|
451
|
+
text: options.to_s,
|
452
|
+
feedback_text: "Copied!",
|
453
|
+
position: "top",
|
454
|
+
duration: 2000
|
455
|
+
}
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
459
|
+
def setup_confirmation_options(options, additional_classes, confirm, wrapper_data)
|
460
|
+
return unless confirm.present?
|
461
|
+
|
462
|
+
confirm_config = normalize_confirmation_options(confirm)
|
463
|
+
|
464
|
+
# Use the same theme processing as regular buttons
|
465
|
+
confirm_theme_styles = process_theme(:solid, { name: confirm_config[:variant] })
|
466
|
+
cancel_theme_styles = process_theme(:subtle, { name: :secondary })
|
467
|
+
|
468
|
+
wrapper_data.merge!(
|
469
|
+
controller: "confirmation",
|
470
|
+
confirmation_title_value: confirm_config[:title],
|
471
|
+
confirmation_message_value: confirm_config[:message],
|
472
|
+
confirmation_icon_color_value: confirm_config[:variant],
|
473
|
+
confirmation_confirm_text_value: confirm_config[:confirm_text],
|
474
|
+
confirmation_cancel_text_value: confirm_config[:cancel_text],
|
475
|
+
confirmation_confirm_styles_value: confirm_theme_styles,
|
476
|
+
confirmation_cancel_styles_value: cancel_theme_styles
|
477
|
+
)
|
478
|
+
|
479
|
+
# Only add loading state if enabled
|
480
|
+
if confirm_config[:loading]
|
481
|
+
wrapper_data.merge!(
|
482
|
+
confirmation_loading_value: "true",
|
483
|
+
confirmation_loading_text_value: confirm_config[:loading_text]
|
484
|
+
)
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
def normalize_confirmation_options(options)
|
489
|
+
if options.is_a?(String)
|
490
|
+
{
|
491
|
+
title: "Confirm Action",
|
492
|
+
message: options,
|
493
|
+
variant: :info,
|
494
|
+
confirm_text: "Confirm",
|
495
|
+
cancel_text: "Cancel"
|
496
|
+
}
|
497
|
+
else
|
498
|
+
{
|
499
|
+
title: options[:title] || "Confirm Action",
|
500
|
+
message: options[:message],
|
501
|
+
variant: options[:variant] || :info,
|
502
|
+
confirm_text: options[:confirm_text] || "Confirm",
|
503
|
+
cancel_text: options[:cancel_text] || "Cancel",
|
504
|
+
loading: options[:loading] || false,
|
505
|
+
loading_text: options[:loading_text] || "Processing..."
|
506
|
+
}
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
def render_button(content, variant_class, size_class, radius_class, gradient_class, icon, icon_position, icon_only,
|
362
511
|
loading, loading_text, additional_classes, disabled, options, href, underline,
|
363
512
|
dropdown, dropdown_items, dropdown_icon, wrapper_options)
|
364
513
|
|
@@ -368,6 +517,7 @@ module WildayUi
|
|
368
517
|
variant_class: variant_class,
|
369
518
|
size_class: size_class,
|
370
519
|
radius_class: radius_class,
|
520
|
+
gradient_class: gradient_class,
|
371
521
|
icon: icon,
|
372
522
|
icon_position: icon_position,
|
373
523
|
icon_only: icon_only,
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module WildayUi
|
2
|
+
module ThemeHelper
|
3
|
+
def generate_theme_css_variables
|
4
|
+
colors = WildayUi::Config::Theme.configuration.colors
|
5
|
+
css_vars = colors.map do |color_name, shades|
|
6
|
+
shades.map do |shade, value|
|
7
|
+
"--w-color-#{color_name}-#{shade}: #{value};"
|
8
|
+
end
|
9
|
+
end.flatten.join("\n")
|
10
|
+
|
11
|
+
"<style>:root { #{css_vars} }</style>".html_safe
|
12
|
+
end
|
13
|
+
|
14
|
+
# Helper to get specific color value
|
15
|
+
def theme_color(name, shade = "500")
|
16
|
+
WildayUi::Config::Theme.configuration.colors.dig(name.to_s, shade.to_s)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static targets = ["button", "feedback"];
|
5
|
+
static values = {
|
6
|
+
text: String,
|
7
|
+
feedbackText: { type: String, default: "Copied!" },
|
8
|
+
feedbackPosition: { type: String, default: "top" },
|
9
|
+
feedbackDuration: { type: Number, default: 2000 },
|
10
|
+
};
|
11
|
+
|
12
|
+
connect() {
|
13
|
+
// Optional: Initialize any necessary setup
|
14
|
+
}
|
15
|
+
|
16
|
+
async copy(event) {
|
17
|
+
event.preventDefault();
|
18
|
+
|
19
|
+
try {
|
20
|
+
await navigator.clipboard.writeText(this.textValue);
|
21
|
+
this.showFeedback();
|
22
|
+
} catch (err) {
|
23
|
+
console.error("Failed to copy text:", err);
|
24
|
+
// Fallback for older browsers
|
25
|
+
this.fallbackCopy();
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
fallbackCopy() {
|
30
|
+
const textArea = document.createElement("textarea");
|
31
|
+
textArea.value = this.textValue;
|
32
|
+
textArea.style.position = "fixed";
|
33
|
+
textArea.style.left = "-9999px";
|
34
|
+
document.body.appendChild(textArea);
|
35
|
+
textArea.select();
|
36
|
+
|
37
|
+
try {
|
38
|
+
document.execCommand("copy");
|
39
|
+
this.showFeedback();
|
40
|
+
} catch (err) {
|
41
|
+
console.error("Fallback: Oops, unable to copy", err);
|
42
|
+
}
|
43
|
+
|
44
|
+
document.body.removeChild(textArea);
|
45
|
+
}
|
46
|
+
|
47
|
+
showFeedback() {
|
48
|
+
const feedback = this.hasFeedbackTarget
|
49
|
+
? this.feedbackTarget
|
50
|
+
: this.createFeedbackElement();
|
51
|
+
feedback.textContent = this.feedbackTextValue;
|
52
|
+
|
53
|
+
// Remove any existing position classes
|
54
|
+
feedback.className = "w-button-feedback";
|
55
|
+
|
56
|
+
// Add position-specific classes
|
57
|
+
const positionClasses = this.feedbackPositionValue.split("-");
|
58
|
+
positionClasses.forEach((pos) => {
|
59
|
+
feedback.classList.add(`w-button-feedback-${pos}`);
|
60
|
+
});
|
61
|
+
|
62
|
+
feedback.classList.add("w-button-feedback-show");
|
63
|
+
|
64
|
+
setTimeout(() => {
|
65
|
+
feedback.classList.remove("w-button-feedback-show");
|
66
|
+
}, this.feedbackDurationValue);
|
67
|
+
}
|
68
|
+
|
69
|
+
createFeedbackElement() {
|
70
|
+
const feedback = document.createElement("div");
|
71
|
+
feedback.classList.add("w-button-feedback");
|
72
|
+
feedback.setAttribute("data-clipboard-target", "feedback");
|
73
|
+
this.element.appendChild(feedback);
|
74
|
+
return feedback;
|
75
|
+
}
|
76
|
+
}
|
@@ -0,0 +1,216 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static targets = ["dialog", "confirmButton", "cancelButton"];
|
5
|
+
static values = {
|
6
|
+
title: String,
|
7
|
+
message: String,
|
8
|
+
iconColor: String,
|
9
|
+
confirmText: String,
|
10
|
+
cancelText: String,
|
11
|
+
confirmStyles: String,
|
12
|
+
cancelStyles: String,
|
13
|
+
};
|
14
|
+
|
15
|
+
// Store the original event to be used later
|
16
|
+
originalEvent = null;
|
17
|
+
|
18
|
+
connect() {
|
19
|
+
// Create and append dialog if it doesn't exist
|
20
|
+
if (!this.hasDialogTarget) {
|
21
|
+
this.element.insertAdjacentHTML("beforeend", this.dialogHTML);
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
disconnect() {
|
26
|
+
this.originalEvent = null;
|
27
|
+
this.isConfirmed = false;
|
28
|
+
}
|
29
|
+
|
30
|
+
showDialog(event) {
|
31
|
+
// Don't show dialog if already confirmed
|
32
|
+
if (this.isConfirmed) {
|
33
|
+
this.isConfirmed = false;
|
34
|
+
return;
|
35
|
+
}
|
36
|
+
|
37
|
+
// console.log("Show dialog triggered", event);
|
38
|
+
event.preventDefault();
|
39
|
+
// Store the original event and element
|
40
|
+
this.originalEvent = {
|
41
|
+
type: event.type,
|
42
|
+
element: event.currentTarget,
|
43
|
+
ctrlKey: event.ctrlKey,
|
44
|
+
metaKey: event.metaKey,
|
45
|
+
};
|
46
|
+
// console.log("Original event stored:", this.originalEvent);
|
47
|
+
this.dialogTarget.showModal();
|
48
|
+
this.focusConfirmButton();
|
49
|
+
}
|
50
|
+
|
51
|
+
confirm(event) {
|
52
|
+
// console.log("Confirm clicked");
|
53
|
+
event.preventDefault();
|
54
|
+
this.dialogTarget.close();
|
55
|
+
|
56
|
+
if (this.originalEvent?.element) {
|
57
|
+
const element = this.originalEvent.element;
|
58
|
+
// console.log("Processing element:", element);
|
59
|
+
|
60
|
+
// Let Turbo handle its own elements
|
61
|
+
if (
|
62
|
+
this.hasTurbo &&
|
63
|
+
!element.hasAttribute("data-turbo") &&
|
64
|
+
!element.hasAttribute("data-turbo-method")
|
65
|
+
) {
|
66
|
+
this.resumeOriginalEvent();
|
67
|
+
return;
|
68
|
+
}
|
69
|
+
|
70
|
+
// Dispatch standard DOM custom event
|
71
|
+
const confirmEvent = new CustomEvent("confirm", {
|
72
|
+
bubbles: true,
|
73
|
+
cancelable: true,
|
74
|
+
detail: {
|
75
|
+
element: element,
|
76
|
+
originalEvent: this.originalEvent,
|
77
|
+
},
|
78
|
+
});
|
79
|
+
|
80
|
+
const wasHandled = !element.dispatchEvent(confirmEvent);
|
81
|
+
if (wasHandled) return;
|
82
|
+
|
83
|
+
// If not handled by custom event, resume original event
|
84
|
+
this.resumeOriginalEvent();
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
resumeOriginalEvent() {
|
89
|
+
if (!this.originalEvent) return;
|
90
|
+
|
91
|
+
const element = this.originalEvent.element;
|
92
|
+
// console.log("Resuming original event for:", element);
|
93
|
+
|
94
|
+
// Set flag before triggering the event
|
95
|
+
this.isConfirmed = true;
|
96
|
+
|
97
|
+
// Handle form submissions
|
98
|
+
if (element.closest("form")) {
|
99
|
+
const form = element.closest("form");
|
100
|
+
// console.log("Submitting form:", form);
|
101
|
+
const submitEvent = new Event("submit", {
|
102
|
+
bubbles: true,
|
103
|
+
cancelable: true,
|
104
|
+
});
|
105
|
+
form.dispatchEvent(submitEvent); // This will trigger the event listener
|
106
|
+
this.originalEvent = null;
|
107
|
+
return;
|
108
|
+
}
|
109
|
+
|
110
|
+
// Handle links
|
111
|
+
if (element.tagName === "A" || element.hasAttribute("href")) {
|
112
|
+
// console.log("Processing link click");
|
113
|
+
const click = new MouseEvent("click", {
|
114
|
+
bubbles: true,
|
115
|
+
cancelable: true,
|
116
|
+
ctrlKey: this.originalEvent.ctrlKey,
|
117
|
+
metaKey: this.originalEvent.metaKey,
|
118
|
+
});
|
119
|
+
element.dispatchEvent(click);
|
120
|
+
this.originalEvent = null;
|
121
|
+
return;
|
122
|
+
}
|
123
|
+
|
124
|
+
// Handle regular button click
|
125
|
+
if (
|
126
|
+
!element.closest("form") &&
|
127
|
+
!(element.tagName === "A" || element.hasAttribute("href"))
|
128
|
+
) {
|
129
|
+
// console.log("Processing button click");
|
130
|
+
element.click();
|
131
|
+
this.originalEvent = null;
|
132
|
+
return;
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
cancel(event) {
|
137
|
+
event.preventDefault();
|
138
|
+
this.closeDialog();
|
139
|
+
}
|
140
|
+
|
141
|
+
closeDialog() {
|
142
|
+
this.dialogTarget.close();
|
143
|
+
this.originalEvent = null;
|
144
|
+
}
|
145
|
+
|
146
|
+
handleKeydown(event) {
|
147
|
+
if (event.key === "Escape") {
|
148
|
+
this.cancel(event);
|
149
|
+
}
|
150
|
+
}
|
151
|
+
|
152
|
+
handleClickOutside(event) {
|
153
|
+
if (event.target === this.dialogTarget) {
|
154
|
+
this.cancel(event);
|
155
|
+
}
|
156
|
+
}
|
157
|
+
|
158
|
+
focusConfirmButton() {
|
159
|
+
this.confirmButtonTarget.focus();
|
160
|
+
}
|
161
|
+
|
162
|
+
get hasTurbo() {
|
163
|
+
return typeof Turbo !== "undefined";
|
164
|
+
}
|
165
|
+
|
166
|
+
get dialogHTML() {
|
167
|
+
return `
|
168
|
+
<dialog class="w-button-confirmation-dialog"
|
169
|
+
data-confirmation-target="dialog"
|
170
|
+
data-action="click->confirmation#handleClickOutside keydown->confirmation#handleKeydown">
|
171
|
+
<div class="w-button-confirmation-dialog-content">
|
172
|
+
<div class="w-button-confirmation-dialog-icon ${this.iconColorValue}">
|
173
|
+
${this.iconHTML}
|
174
|
+
</div>
|
175
|
+
|
176
|
+
<h3 class="w-button-confirmation-dialog-title">
|
177
|
+
${this.titleValue}
|
178
|
+
</h3>
|
179
|
+
|
180
|
+
<div class="w-button-confirmation-dialog-message">
|
181
|
+
${this.messageValue}
|
182
|
+
</div>
|
183
|
+
|
184
|
+
<div class="w-button-confirmation-dialog-actions">
|
185
|
+
<button data-confirmation-target="cancelButton"
|
186
|
+
data-action="click->confirmation#cancel"
|
187
|
+
class="w-button w-button-subtle w-button-medium w-button-rounded"
|
188
|
+
style="${this.cancelStylesValue}">
|
189
|
+
${this.cancelTextValue}
|
190
|
+
</button>
|
191
|
+
|
192
|
+
<button data-confirmation-target="confirmButton"
|
193
|
+
data-action="click->confirmation#confirm"
|
194
|
+
class="w-button w-button-solid w-button-medium w-button-rounded"
|
195
|
+
style="${this.confirmStylesValue}">
|
196
|
+
${this.confirmTextValue}
|
197
|
+
</button>
|
198
|
+
</div>
|
199
|
+
</div>
|
200
|
+
</dialog>
|
201
|
+
`;
|
202
|
+
}
|
203
|
+
|
204
|
+
get iconHTML() {
|
205
|
+
const icons = {
|
206
|
+
info: '<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>',
|
207
|
+
success:
|
208
|
+
'<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>',
|
209
|
+
warning:
|
210
|
+
'<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" /></svg>',
|
211
|
+
danger:
|
212
|
+
'<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>',
|
213
|
+
};
|
214
|
+
return icons[this.iconColorValue] || icons.info;
|
215
|
+
}
|
216
|
+
}
|
@@ -1,7 +1,8 @@
|
|
1
1
|
import { Application } from "@hotwired/stimulus";
|
2
2
|
import ButtonController from "./button_controller";
|
3
3
|
import DropdownController from "./dropdown_controller";
|
4
|
-
|
4
|
+
import ClipboardController from "./clipboard_controller";
|
5
|
+
import ConfirmationController from "./confirmation_controller";
|
5
6
|
// Initialize Stimulus
|
6
7
|
const application = Application.start();
|
7
8
|
window.Stimulus = application;
|
@@ -9,6 +10,8 @@ window.Stimulus = application;
|
|
9
10
|
// Register the button controller
|
10
11
|
application.register("button", ButtonController);
|
11
12
|
application.register("dropdown", DropdownController);
|
13
|
+
application.register("clipboard", ClipboardController);
|
14
|
+
application.register("confirmation", ConfirmationController);
|
12
15
|
// Debug check to ensure Stimulus is loaded
|
13
16
|
// if (window.Stimulus) {
|
14
17
|
// console.log("✅ Stimulus is loaded and initialized.");
|
@@ -111,12 +111,12 @@ module WildayUi
|
|
111
111
|
"100" => "#F3F4F6",
|
112
112
|
"200" => "#E5E7EB",
|
113
113
|
"300" => "#D1D5DB",
|
114
|
-
"400" => "#
|
115
|
-
"500" => "#
|
116
|
-
"600" => "#
|
117
|
-
"700" => "#
|
118
|
-
"800" => "#
|
119
|
-
"900" => "#
|
114
|
+
"400" => "#1F2937",
|
115
|
+
"500" => "#111827",
|
116
|
+
"600" => "#0F172A",
|
117
|
+
"700" => "#0A0F1A",
|
118
|
+
"800" => "#060912",
|
119
|
+
"900" => "#030509"
|
120
120
|
},
|
121
121
|
"link" => {
|
122
122
|
"50" => "#EFF6FF",
|
data/lib/wilday_ui/version.rb
CHANGED