wilday_ui 0.5.6 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 50912590c0a438d5c271b389672df9d96c03ddf8001899804d072ddb9e18e925
|
4
|
+
data.tar.gz: 8924aaef953638212799214a462b906eb05c010a260670e78977e683200b9716
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d58f3efc56e7e0e32330dd9f5fa5b7098271926a00eeca6c594afe1e496abba345438a82d654a5c0952847e5edc875ed754487135580bfc4e19879b6f801216
|
7
|
+
data.tar.gz: a771bc6e4cbd382061fa53349d9232cec601776158ff18160bb41132dad50bafaa84286a3c90993a91bc888beab239890ce2088a0ece112cd7abcc2d4404809c
|
data/README.md
CHANGED
@@ -4,6 +4,13 @@ WildayUI is a simple, minimalist, and customizable library of pre-built componen
|
|
4
4
|
WildayUI's main goal is to provide **static components** (such as buttons, badges, etc.) and **dynamic components** (such as dropdowns, modals, etc.) that are easily customizable and extendable. Each page in the component documentation is divided into sections for static and dynamic components.
|
5
5
|
|
6
6
|
---
|
7
|
+
|
8
|
+
## Demo
|
9
|
+
|
10
|
+
You can see a demo of WildayUI [here](https://wildayuidemo.onrender.com/).
|
11
|
+
|
12
|
+
---
|
13
|
+
|
7
14
|
## Installation
|
8
15
|
To start using Wilday UI, add it to your Gemfile:
|
9
16
|
```ruby
|
@@ -2708,11 +2708,234 @@ var dropdown_controller_default = class extends Controller {
|
|
2708
2708
|
}
|
2709
2709
|
};
|
2710
2710
|
|
2711
|
+
// app/javascript/wilday_ui/controllers/clipboard_controller.js
|
2712
|
+
var clipboard_controller_default = class extends Controller {
|
2713
|
+
static targets = ["button", "feedback"];
|
2714
|
+
static values = {
|
2715
|
+
text: String,
|
2716
|
+
feedbackText: { type: String, default: "Copied!" },
|
2717
|
+
feedbackPosition: { type: String, default: "top" },
|
2718
|
+
feedbackDuration: { type: Number, default: 2e3 }
|
2719
|
+
};
|
2720
|
+
connect() {
|
2721
|
+
}
|
2722
|
+
async copy(event) {
|
2723
|
+
event.preventDefault();
|
2724
|
+
try {
|
2725
|
+
await navigator.clipboard.writeText(this.textValue);
|
2726
|
+
this.showFeedback();
|
2727
|
+
} catch (err) {
|
2728
|
+
console.error("Failed to copy text:", err);
|
2729
|
+
this.fallbackCopy();
|
2730
|
+
}
|
2731
|
+
}
|
2732
|
+
fallbackCopy() {
|
2733
|
+
const textArea = document.createElement("textarea");
|
2734
|
+
textArea.value = this.textValue;
|
2735
|
+
textArea.style.position = "fixed";
|
2736
|
+
textArea.style.left = "-9999px";
|
2737
|
+
document.body.appendChild(textArea);
|
2738
|
+
textArea.select();
|
2739
|
+
try {
|
2740
|
+
document.execCommand("copy");
|
2741
|
+
this.showFeedback();
|
2742
|
+
} catch (err) {
|
2743
|
+
console.error("Fallback: Oops, unable to copy", err);
|
2744
|
+
}
|
2745
|
+
document.body.removeChild(textArea);
|
2746
|
+
}
|
2747
|
+
showFeedback() {
|
2748
|
+
const feedback = this.hasFeedbackTarget ? this.feedbackTarget : this.createFeedbackElement();
|
2749
|
+
feedback.textContent = this.feedbackTextValue;
|
2750
|
+
feedback.className = "w-button-feedback";
|
2751
|
+
const positionClasses = this.feedbackPositionValue.split("-");
|
2752
|
+
positionClasses.forEach((pos) => {
|
2753
|
+
feedback.classList.add(`w-button-feedback-${pos}`);
|
2754
|
+
});
|
2755
|
+
feedback.classList.add("w-button-feedback-show");
|
2756
|
+
setTimeout(() => {
|
2757
|
+
feedback.classList.remove("w-button-feedback-show");
|
2758
|
+
}, this.feedbackDurationValue);
|
2759
|
+
}
|
2760
|
+
createFeedbackElement() {
|
2761
|
+
const feedback = document.createElement("div");
|
2762
|
+
feedback.classList.add("w-button-feedback");
|
2763
|
+
feedback.setAttribute("data-clipboard-target", "feedback");
|
2764
|
+
this.element.appendChild(feedback);
|
2765
|
+
return feedback;
|
2766
|
+
}
|
2767
|
+
};
|
2768
|
+
|
2769
|
+
// app/javascript/wilday_ui/controllers/confirmation_controller.js
|
2770
|
+
var confirmation_controller_default = class extends Controller {
|
2771
|
+
static targets = ["dialog", "confirmButton", "cancelButton"];
|
2772
|
+
static values = {
|
2773
|
+
title: String,
|
2774
|
+
message: String,
|
2775
|
+
iconColor: String,
|
2776
|
+
confirmText: String,
|
2777
|
+
cancelText: String,
|
2778
|
+
confirmStyles: String,
|
2779
|
+
cancelStyles: String
|
2780
|
+
};
|
2781
|
+
// Store the original event to be used later
|
2782
|
+
originalEvent = null;
|
2783
|
+
connect() {
|
2784
|
+
if (!this.hasDialogTarget) {
|
2785
|
+
this.element.insertAdjacentHTML("beforeend", this.dialogHTML);
|
2786
|
+
}
|
2787
|
+
}
|
2788
|
+
disconnect() {
|
2789
|
+
this.originalEvent = null;
|
2790
|
+
this.isConfirmed = false;
|
2791
|
+
}
|
2792
|
+
showDialog(event) {
|
2793
|
+
if (this.isConfirmed) {
|
2794
|
+
this.isConfirmed = false;
|
2795
|
+
return;
|
2796
|
+
}
|
2797
|
+
event.preventDefault();
|
2798
|
+
this.originalEvent = {
|
2799
|
+
type: event.type,
|
2800
|
+
element: event.currentTarget,
|
2801
|
+
ctrlKey: event.ctrlKey,
|
2802
|
+
metaKey: event.metaKey
|
2803
|
+
};
|
2804
|
+
this.dialogTarget.showModal();
|
2805
|
+
this.focusConfirmButton();
|
2806
|
+
}
|
2807
|
+
confirm(event) {
|
2808
|
+
event.preventDefault();
|
2809
|
+
this.dialogTarget.close();
|
2810
|
+
if (this.originalEvent?.element) {
|
2811
|
+
const element = this.originalEvent.element;
|
2812
|
+
if (this.hasTurbo && !element.hasAttribute("data-turbo") && !element.hasAttribute("data-turbo-method")) {
|
2813
|
+
this.resumeOriginalEvent();
|
2814
|
+
return;
|
2815
|
+
}
|
2816
|
+
const confirmEvent = new CustomEvent("confirm", {
|
2817
|
+
bubbles: true,
|
2818
|
+
cancelable: true,
|
2819
|
+
detail: {
|
2820
|
+
element,
|
2821
|
+
originalEvent: this.originalEvent
|
2822
|
+
}
|
2823
|
+
});
|
2824
|
+
const wasHandled = !element.dispatchEvent(confirmEvent);
|
2825
|
+
if (wasHandled) return;
|
2826
|
+
this.resumeOriginalEvent();
|
2827
|
+
}
|
2828
|
+
}
|
2829
|
+
resumeOriginalEvent() {
|
2830
|
+
if (!this.originalEvent) return;
|
2831
|
+
const element = this.originalEvent.element;
|
2832
|
+
this.isConfirmed = true;
|
2833
|
+
if (element.closest("form")) {
|
2834
|
+
const form = element.closest("form");
|
2835
|
+
const submitEvent = new Event("submit", {
|
2836
|
+
bubbles: true,
|
2837
|
+
cancelable: true
|
2838
|
+
});
|
2839
|
+
form.dispatchEvent(submitEvent);
|
2840
|
+
this.originalEvent = null;
|
2841
|
+
return;
|
2842
|
+
}
|
2843
|
+
if (element.tagName === "A" || element.hasAttribute("href")) {
|
2844
|
+
const click = new MouseEvent("click", {
|
2845
|
+
bubbles: true,
|
2846
|
+
cancelable: true,
|
2847
|
+
ctrlKey: this.originalEvent.ctrlKey,
|
2848
|
+
metaKey: this.originalEvent.metaKey
|
2849
|
+
});
|
2850
|
+
element.dispatchEvent(click);
|
2851
|
+
this.originalEvent = null;
|
2852
|
+
return;
|
2853
|
+
}
|
2854
|
+
if (!element.closest("form") && !(element.tagName === "A" || element.hasAttribute("href"))) {
|
2855
|
+
element.click();
|
2856
|
+
this.originalEvent = null;
|
2857
|
+
return;
|
2858
|
+
}
|
2859
|
+
}
|
2860
|
+
cancel(event) {
|
2861
|
+
event.preventDefault();
|
2862
|
+
this.closeDialog();
|
2863
|
+
}
|
2864
|
+
closeDialog() {
|
2865
|
+
this.dialogTarget.close();
|
2866
|
+
this.originalEvent = null;
|
2867
|
+
}
|
2868
|
+
handleKeydown(event) {
|
2869
|
+
if (event.key === "Escape") {
|
2870
|
+
this.cancel(event);
|
2871
|
+
}
|
2872
|
+
}
|
2873
|
+
handleClickOutside(event) {
|
2874
|
+
if (event.target === this.dialogTarget) {
|
2875
|
+
this.cancel(event);
|
2876
|
+
}
|
2877
|
+
}
|
2878
|
+
focusConfirmButton() {
|
2879
|
+
this.confirmButtonTarget.focus();
|
2880
|
+
}
|
2881
|
+
get hasTurbo() {
|
2882
|
+
return typeof Turbo !== "undefined";
|
2883
|
+
}
|
2884
|
+
get dialogHTML() {
|
2885
|
+
return `
|
2886
|
+
<dialog class="w-button-confirmation-dialog"
|
2887
|
+
data-confirmation-target="dialog"
|
2888
|
+
data-action="click->confirmation#handleClickOutside keydown->confirmation#handleKeydown">
|
2889
|
+
<div class="w-button-confirmation-dialog-content">
|
2890
|
+
<div class="w-button-confirmation-dialog-icon ${this.iconColorValue}">
|
2891
|
+
${this.iconHTML}
|
2892
|
+
</div>
|
2893
|
+
|
2894
|
+
<h3 class="w-button-confirmation-dialog-title">
|
2895
|
+
${this.titleValue}
|
2896
|
+
</h3>
|
2897
|
+
|
2898
|
+
<div class="w-button-confirmation-dialog-message">
|
2899
|
+
${this.messageValue}
|
2900
|
+
</div>
|
2901
|
+
|
2902
|
+
<div class="w-button-confirmation-dialog-actions">
|
2903
|
+
<button data-confirmation-target="cancelButton"
|
2904
|
+
data-action="click->confirmation#cancel"
|
2905
|
+
class="w-button w-button-subtle w-button-medium w-button-rounded"
|
2906
|
+
style="${this.cancelStylesValue}">
|
2907
|
+
${this.cancelTextValue}
|
2908
|
+
</button>
|
2909
|
+
|
2910
|
+
<button data-confirmation-target="confirmButton"
|
2911
|
+
data-action="click->confirmation#confirm"
|
2912
|
+
class="w-button w-button-solid w-button-medium w-button-rounded"
|
2913
|
+
style="${this.confirmStylesValue}">
|
2914
|
+
${this.confirmTextValue}
|
2915
|
+
</button>
|
2916
|
+
</div>
|
2917
|
+
</div>
|
2918
|
+
</dialog>
|
2919
|
+
`;
|
2920
|
+
}
|
2921
|
+
get iconHTML() {
|
2922
|
+
const icons = {
|
2923
|
+
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>',
|
2924
|
+
success: '<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>',
|
2925
|
+
warning: '<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>',
|
2926
|
+
danger: '<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>'
|
2927
|
+
};
|
2928
|
+
return icons[this.iconColorValue] || icons.info;
|
2929
|
+
}
|
2930
|
+
};
|
2931
|
+
|
2711
2932
|
// app/javascript/wilday_ui/controllers/index.js
|
2712
2933
|
var application = Application.start();
|
2713
2934
|
window.Stimulus = application;
|
2714
2935
|
application.register("button", ButtonController);
|
2715
2936
|
application.register("dropdown", dropdown_controller_default);
|
2937
|
+
application.register("clipboard", clipboard_controller_default);
|
2938
|
+
application.register("confirmation", confirmation_controller_default);
|
2716
2939
|
|
2717
2940
|
// app/javascript/wilday_ui/components/button.js
|
2718
2941
|
document.addEventListener("DOMContentLoaded", () => {
|