ariadne_view_components 0.0.10-x86_64-linux
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 +7 -0
- data/LICENSE.txt +49 -0
- data/README.md +73 -0
- data/app/assets/config/manifest.js +2 -0
- data/app/assets/javascripts/ariadne-form-with.d.ts +20 -0
- data/app/assets/javascripts/ariadne-form.d.ts +22 -0
- data/app/assets/javascripts/ariadne.d.ts +1 -0
- data/app/assets/javascripts/ariadne_view_components.js +8 -0
- data/app/assets/javascripts/ariadne_view_components.js.map +1 -0
- data/app/assets/javascripts/clipboard-copy-component.d.ts +4 -0
- data/app/assets/javascripts/comment-component.d.ts +13 -0
- data/app/assets/javascripts/rich-text-area-component.d.ts +4 -0
- data/app/assets/javascripts/slideover-component.d.ts +9 -0
- data/app/assets/javascripts/time-ago-component.d.ts +1 -0
- data/app/assets/javascripts/time_ago_component.d.ts +1 -0
- data/app/assets/javascripts/tooltip-component.d.ts +24 -0
- data/app/assets/stylesheets/ariadne_view_components.css +6 -0
- data/app/assets/stylesheets/prosemirror.css +323 -0
- data/app/assets/stylesheets/tooltip-component.css +37 -0
- data/app/components/ariadne/ariadne-form.ts +96 -0
- data/app/components/ariadne/ariadne.ts +20 -0
- data/app/components/ariadne/base_button.rb +61 -0
- data/app/components/ariadne/base_component.rb +37 -0
- data/app/components/ariadne/blankslate_component.html.erb +26 -0
- data/app/components/ariadne/blankslate_component.rb +146 -0
- data/app/components/ariadne/body_component.rb +30 -0
- data/app/components/ariadne/button_component.html.erb +4 -0
- data/app/components/ariadne/button_component.rb +157 -0
- data/app/components/ariadne/clipboard-copy-component.ts +19 -0
- data/app/components/ariadne/clipboard_copy_component.html.erb +9 -0
- data/app/components/ariadne/clipboard_copy_component.rb +90 -0
- data/app/components/ariadne/comment-component.ts +55 -0
- data/app/components/ariadne/comment_component.html.erb +22 -0
- data/app/components/ariadne/comment_component.rb +57 -0
- data/app/components/ariadne/component.rb +128 -0
- data/app/components/ariadne/container_component.html.erb +3 -0
- data/app/components/ariadne/container_component.rb +25 -0
- data/app/components/ariadne/content.rb +12 -0
- data/app/components/ariadne/counter_component.rb +100 -0
- data/app/components/ariadne/flash_component.html.erb +31 -0
- data/app/components/ariadne/flash_component.rb +125 -0
- data/app/components/ariadne/flex_component.rb +49 -0
- data/app/components/ariadne/footer_component.html.erb +7 -0
- data/app/components/ariadne/footer_component.rb +23 -0
- data/app/components/ariadne/grid_component.html.erb +26 -0
- data/app/components/ariadne/grid_component.rb +66 -0
- data/app/components/ariadne/header_component.html.erb +29 -0
- data/app/components/ariadne/header_component.rb +114 -0
- data/app/components/ariadne/heading_component.rb +49 -0
- data/app/components/ariadne/heroicon_component.html.erb +4 -0
- data/app/components/ariadne/heroicon_component.rb +129 -0
- data/app/components/ariadne/image_component.rb +53 -0
- data/app/components/ariadne/inline_flex_component.html.erb +5 -0
- data/app/components/ariadne/inline_flex_component.rb +65 -0
- data/app/components/ariadne/link_component.rb +65 -0
- data/app/components/ariadne/list_component.html.erb +15 -0
- data/app/components/ariadne/list_component.rb +68 -0
- data/app/components/ariadne/main_component.rb +32 -0
- data/app/components/ariadne/narrow_container_component.html.erb +3 -0
- data/app/components/ariadne/narrow_container_component.rb +30 -0
- data/app/components/ariadne/panel_bar_component.html.erb +20 -0
- data/app/components/ariadne/panel_bar_component.rb +79 -0
- data/app/components/ariadne/pill_component.html.erb +3 -0
- data/app/components/ariadne/pill_component.rb +30 -0
- data/app/components/ariadne/rich-text-area-component.ts +32 -0
- data/app/components/ariadne/rich_text_area_component.html.erb +6 -0
- data/app/components/ariadne/rich_text_area_component.rb +35 -0
- data/app/components/ariadne/slideover-component.ts +26 -0
- data/app/components/ariadne/slideover_component.html.erb +11 -0
- data/app/components/ariadne/slideover_component.rb +81 -0
- data/app/components/ariadne/tab_bar_component.html.erb +3 -0
- data/app/components/ariadne/tab_bar_component.rb +45 -0
- data/app/components/ariadne/tab_component.html.erb +7 -0
- data/app/components/ariadne/tab_component.rb +43 -0
- data/app/components/ariadne/text.rb +25 -0
- data/app/components/ariadne/time-ago-component.ts +1 -0
- data/app/components/ariadne/time_ago_component.rb +56 -0
- data/app/components/ariadne/timeline_component.html.erb +19 -0
- data/app/components/ariadne/timeline_component.rb +34 -0
- data/app/components/ariadne/tooltip-component.ts +57 -0
- data/app/components/ariadne/tooltip_component.html.erb +4 -0
- data/app/components/ariadne/tooltip_component.rb +108 -0
- data/app/lib/ariadne/action_view_extensions/form_helper.rb +26 -0
- data/app/lib/ariadne/audited/dsl.rb +32 -0
- data/app/lib/ariadne/class_name_helper.rb +22 -0
- data/app/lib/ariadne/fetch_or_fallback_helper.rb +102 -0
- data/app/lib/ariadne/form_builder.rb +71 -0
- data/app/lib/ariadne/icon_helper.rb +47 -0
- data/app/lib/ariadne/join_style_arguments_helper.rb +14 -0
- data/app/lib/ariadne/logger_helper.rb +23 -0
- data/app/lib/ariadne/status/dsl.rb +41 -0
- data/app/lib/ariadne/tab_nav_helper.rb +35 -0
- data/app/lib/ariadne/tabbed_component_helper.rb +39 -0
- data/app/lib/ariadne/test_selector_helper.rb +20 -0
- data/app/lib/ariadne/underline_nav_helper.rb +44 -0
- data/app/lib/ariadne/view_helper.rb +22 -0
- data/exe/tailwindcss +21 -0
- data/exe/x86_64-linux/tailwindcss +0 -0
- data/lib/ariadne/view_components/commands.rb +90 -0
- data/lib/ariadne/view_components/constants.rb +53 -0
- data/lib/ariadne/view_components/engine.rb +75 -0
- data/lib/ariadne/view_components/linters.rb +3 -0
- data/lib/ariadne/view_components/statuses.rb +14 -0
- data/lib/ariadne/view_components/upstream.rb +20 -0
- data/lib/ariadne/view_components/version.rb +7 -0
- data/lib/ariadne/view_components.rb +61 -0
- data/lib/rubocop/config/default.yml +8 -0
- data/lib/rubocop/cop/ariadne/base_cop.rb +26 -0
- data/lib/rubocop/cop/ariadne/no_tag_memoize.rb +44 -0
- data/lib/rubocop/cop/ariadne.rb +3 -0
- data/lib/tasks/ariadne_view_components.rake +48 -0
- data/lib/tasks/build.rake +30 -0
- data/lib/tasks/coverage.rake +19 -0
- data/lib/tasks/custom_utilities.yml +310 -0
- data/lib/tasks/docs.rake +524 -0
- data/lib/tasks/helpers/ast_processor.rb +44 -0
- data/lib/tasks/helpers/ast_traverser.rb +77 -0
- data/lib/tasks/static.rake +15 -0
- data/lib/yard/docs_helper.rb +83 -0
- data/lib/yard/renders_many_handler.rb +19 -0
- data/lib/yard/renders_one_handler.rb +19 -0
- data/static/arguments.yml +619 -0
- data/static/assets/view-components.svg +18 -0
- data/static/audited_at.json +38 -0
- data/static/classes.yml +291 -0
- data/static/constants.json +426 -0
- data/static/statuses.json +38 -0
- data/static/tailwindcss.yml +727 -0
- data/tailwind.config.js +65 -0
- metadata +264 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
2
|
+
export default class CommentComponent extends Controller {
|
3
|
+
static targets: string[];
|
4
|
+
readonly commentComponentTarget: HTMLDivElement;
|
5
|
+
readonly tabBarComponentTarget: HTMLElement;
|
6
|
+
readonly tabTargets: [HTMLButtonElement];
|
7
|
+
SELECTED_TAB_CLASSES: string[];
|
8
|
+
PUBLIC_BACKGROUND_COLOR: string;
|
9
|
+
INTERNAL_BACKGROUND_COLOR: string;
|
10
|
+
connect(): void;
|
11
|
+
toggleTab(): void;
|
12
|
+
toggleBackgrounds(tab: HTMLButtonElement): void;
|
13
|
+
}
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
2
|
+
export default class SlideoverComponent extends Controller {
|
3
|
+
static targets: string[];
|
4
|
+
readonly expandableTarget: HTMLDivElement;
|
5
|
+
readonly expandWrapperTarget: HTMLDivElement;
|
6
|
+
readonly slidePanelTargets: [HTMLDivElement];
|
7
|
+
readonly buttonWrapperTarget: HTMLDivElement;
|
8
|
+
toggle(): void;
|
9
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
import '@github/time-elements';
|
@@ -0,0 +1 @@
|
|
1
|
+
import '@github/time-elements';
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import { Controller } from '@hotwired/stimulus';
|
2
|
+
import type { Instance, Placement } from '@popperjs/core';
|
3
|
+
export default class TooltipComponent extends Controller {
|
4
|
+
static targets: string[];
|
5
|
+
readonly triggerTarget: HTMLElement;
|
6
|
+
readonly tooltipTarget: HTMLElement;
|
7
|
+
static values: {
|
8
|
+
placement: {
|
9
|
+
type: StringConstructor;
|
10
|
+
default: string;
|
11
|
+
};
|
12
|
+
offset: {
|
13
|
+
type: ArrayConstructor;
|
14
|
+
default: number[];
|
15
|
+
};
|
16
|
+
};
|
17
|
+
readonly placementValue: Placement;
|
18
|
+
readonly offsetValue: Array<number>;
|
19
|
+
popperInstance: Instance;
|
20
|
+
connect(): void;
|
21
|
+
disconnect(): void;
|
22
|
+
show(): void;
|
23
|
+
hide(): void;
|
24
|
+
}
|
@@ -0,0 +1,323 @@
|
|
1
|
+
.ProseMirror {
|
2
|
+
position: relative;
|
3
|
+
}
|
4
|
+
|
5
|
+
.ProseMirror {
|
6
|
+
word-wrap: break-word;
|
7
|
+
white-space: pre-wrap;
|
8
|
+
-webkit-font-variant-ligatures: none;
|
9
|
+
font-variant-ligatures: none;
|
10
|
+
}
|
11
|
+
|
12
|
+
.ProseMirror pre {
|
13
|
+
white-space: pre-wrap;
|
14
|
+
}
|
15
|
+
|
16
|
+
.ProseMirror li {
|
17
|
+
position: relative;
|
18
|
+
}
|
19
|
+
|
20
|
+
.ProseMirror-hideselection *::selection {
|
21
|
+
background: transparent;
|
22
|
+
}
|
23
|
+
.ProseMirror-hideselection *::-moz-selection {
|
24
|
+
background: transparent;
|
25
|
+
}
|
26
|
+
.ProseMirror-hideselection {
|
27
|
+
caret-color: transparent;
|
28
|
+
}
|
29
|
+
|
30
|
+
.ProseMirror-selectednode {
|
31
|
+
outline: 2px solid #8cf;
|
32
|
+
}
|
33
|
+
|
34
|
+
/* Make sure li selections wrap around markers */
|
35
|
+
|
36
|
+
li.ProseMirror-selectednode {
|
37
|
+
outline: none;
|
38
|
+
}
|
39
|
+
|
40
|
+
li.ProseMirror-selectednode:after {
|
41
|
+
content: '';
|
42
|
+
position: absolute;
|
43
|
+
left: -32px;
|
44
|
+
right: -2px;
|
45
|
+
top: -2px;
|
46
|
+
bottom: -2px;
|
47
|
+
border: 2px solid #8cf;
|
48
|
+
pointer-events: none;
|
49
|
+
}
|
50
|
+
.ProseMirror-textblock-dropdown {
|
51
|
+
min-width: 3em;
|
52
|
+
}
|
53
|
+
|
54
|
+
.ProseMirror-menu {
|
55
|
+
margin: 0 -4px;
|
56
|
+
line-height: 1;
|
57
|
+
}
|
58
|
+
|
59
|
+
.ProseMirror-tooltip .ProseMirror-menu {
|
60
|
+
width: -webkit-fit-content;
|
61
|
+
width: fit-content;
|
62
|
+
white-space: pre;
|
63
|
+
}
|
64
|
+
|
65
|
+
.ProseMirror-menuitem {
|
66
|
+
margin-right: 3px;
|
67
|
+
display: inline-block;
|
68
|
+
}
|
69
|
+
|
70
|
+
.ProseMirror-menuseparator {
|
71
|
+
border-right: 1px solid #ddd;
|
72
|
+
margin-right: 3px;
|
73
|
+
}
|
74
|
+
|
75
|
+
.ProseMirror-menu-dropdown,
|
76
|
+
.ProseMirror-menu-dropdown-menu {
|
77
|
+
font-size: 90%;
|
78
|
+
white-space: nowrap;
|
79
|
+
}
|
80
|
+
|
81
|
+
.ProseMirror-menu-dropdown {
|
82
|
+
vertical-align: 1px;
|
83
|
+
cursor: pointer;
|
84
|
+
position: relative;
|
85
|
+
padding-right: 15px;
|
86
|
+
}
|
87
|
+
|
88
|
+
.ProseMirror-menu-dropdown-wrap {
|
89
|
+
padding: 1px 0 1px 4px;
|
90
|
+
display: inline-block;
|
91
|
+
position: relative;
|
92
|
+
}
|
93
|
+
|
94
|
+
.ProseMirror-menu-dropdown:after {
|
95
|
+
content: '';
|
96
|
+
border-left: 4px solid transparent;
|
97
|
+
border-right: 4px solid transparent;
|
98
|
+
border-top: 4px solid currentColor;
|
99
|
+
opacity: 0.6;
|
100
|
+
position: absolute;
|
101
|
+
right: 4px;
|
102
|
+
top: calc(50% - 2px);
|
103
|
+
}
|
104
|
+
|
105
|
+
.ProseMirror-menu-dropdown-menu,
|
106
|
+
.ProseMirror-menu-submenu {
|
107
|
+
position: absolute;
|
108
|
+
background: white;
|
109
|
+
color: #666;
|
110
|
+
border: 1px solid #aaa;
|
111
|
+
padding: 2px;
|
112
|
+
}
|
113
|
+
|
114
|
+
.ProseMirror-menu-dropdown-menu {
|
115
|
+
z-index: 15;
|
116
|
+
min-width: 6em;
|
117
|
+
}
|
118
|
+
|
119
|
+
.ProseMirror-menu-dropdown-item {
|
120
|
+
cursor: pointer;
|
121
|
+
padding: 2px 8px 2px 4px;
|
122
|
+
}
|
123
|
+
|
124
|
+
.ProseMirror-menu-dropdown-item:hover {
|
125
|
+
background: #f2f2f2;
|
126
|
+
}
|
127
|
+
|
128
|
+
.ProseMirror-menu-submenu-wrap {
|
129
|
+
position: relative;
|
130
|
+
margin-right: -4px;
|
131
|
+
}
|
132
|
+
|
133
|
+
.ProseMirror-menu-submenu-label:after {
|
134
|
+
content: '';
|
135
|
+
border-top: 4px solid transparent;
|
136
|
+
border-bottom: 4px solid transparent;
|
137
|
+
border-left: 4px solid currentColor;
|
138
|
+
opacity: 0.6;
|
139
|
+
position: absolute;
|
140
|
+
right: 4px;
|
141
|
+
top: calc(50% - 4px);
|
142
|
+
}
|
143
|
+
|
144
|
+
.ProseMirror-menu-submenu {
|
145
|
+
display: none;
|
146
|
+
min-width: 4em;
|
147
|
+
left: 100%;
|
148
|
+
top: -3px;
|
149
|
+
}
|
150
|
+
|
151
|
+
.ProseMirror-menu-active {
|
152
|
+
background: #eee;
|
153
|
+
border-radius: 4px;
|
154
|
+
}
|
155
|
+
|
156
|
+
.ProseMirror-menu-active {
|
157
|
+
background: #eee;
|
158
|
+
border-radius: 4px;
|
159
|
+
}
|
160
|
+
|
161
|
+
.ProseMirror-menu-disabled {
|
162
|
+
opacity: 0.3;
|
163
|
+
}
|
164
|
+
|
165
|
+
.ProseMirror-menu-submenu-wrap:hover .ProseMirror-menu-submenu,
|
166
|
+
.ProseMirror-menu-submenu-wrap-active .ProseMirror-menu-submenu {
|
167
|
+
display: block;
|
168
|
+
}
|
169
|
+
|
170
|
+
.ProseMirror-menubar {
|
171
|
+
border-top-left-radius: inherit;
|
172
|
+
border-top-right-radius: inherit;
|
173
|
+
position: relative;
|
174
|
+
min-height: 1em;
|
175
|
+
color: #666;
|
176
|
+
padding: 1px 6px;
|
177
|
+
top: 0;
|
178
|
+
left: 0;
|
179
|
+
right: 0;
|
180
|
+
border-bottom: 1px solid silver;
|
181
|
+
background: white;
|
182
|
+
z-index: 10;
|
183
|
+
-moz-box-sizing: border-box;
|
184
|
+
box-sizing: border-box;
|
185
|
+
overflow: visible;
|
186
|
+
}
|
187
|
+
|
188
|
+
.ProseMirror-icon {
|
189
|
+
display: inline-block;
|
190
|
+
line-height: 0.8;
|
191
|
+
vertical-align: -2px; /* Compensate for padding */
|
192
|
+
padding: 2px 8px;
|
193
|
+
cursor: pointer;
|
194
|
+
}
|
195
|
+
|
196
|
+
.ProseMirror-menu-disabled.ProseMirror-icon {
|
197
|
+
cursor: default;
|
198
|
+
}
|
199
|
+
|
200
|
+
.ProseMirror-icon svg {
|
201
|
+
fill: currentColor;
|
202
|
+
height: 1em;
|
203
|
+
}
|
204
|
+
|
205
|
+
.ProseMirror-icon span {
|
206
|
+
vertical-align: text-top;
|
207
|
+
}
|
208
|
+
/* Add space around the hr to make clicking it easier */
|
209
|
+
|
210
|
+
.ProseMirror-example-setup-style hr {
|
211
|
+
padding: 2px 10px;
|
212
|
+
border: none;
|
213
|
+
margin: 1em 0;
|
214
|
+
}
|
215
|
+
|
216
|
+
.ProseMirror-example-setup-style hr:after {
|
217
|
+
content: '';
|
218
|
+
display: block;
|
219
|
+
height: 1px;
|
220
|
+
background-color: silver;
|
221
|
+
line-height: 2px;
|
222
|
+
}
|
223
|
+
|
224
|
+
.ProseMirror ul,
|
225
|
+
.ProseMirror ol {
|
226
|
+
padding-left: 30px;
|
227
|
+
}
|
228
|
+
|
229
|
+
.ProseMirror blockquote {
|
230
|
+
padding-left: 1em;
|
231
|
+
border-left: 3px solid #eee;
|
232
|
+
margin-left: 0;
|
233
|
+
margin-right: 0;
|
234
|
+
}
|
235
|
+
|
236
|
+
.ProseMirror-example-setup-style img {
|
237
|
+
cursor: default;
|
238
|
+
}
|
239
|
+
|
240
|
+
.ProseMirror-prompt {
|
241
|
+
background: white;
|
242
|
+
padding: 5px 10px 5px 15px;
|
243
|
+
border: 1px solid silver;
|
244
|
+
position: fixed;
|
245
|
+
border-radius: 3px;
|
246
|
+
z-index: 11;
|
247
|
+
box-shadow: -0.5px 2px 5px rgba(0, 0, 0, 0.2);
|
248
|
+
}
|
249
|
+
|
250
|
+
.ProseMirror-prompt h5 {
|
251
|
+
margin: 0;
|
252
|
+
font-weight: normal;
|
253
|
+
font-size: 100%;
|
254
|
+
color: #444;
|
255
|
+
}
|
256
|
+
|
257
|
+
.ProseMirror-prompt input[type='text'],
|
258
|
+
.ProseMirror-prompt textarea {
|
259
|
+
background: #eee;
|
260
|
+
border: none;
|
261
|
+
outline: none;
|
262
|
+
}
|
263
|
+
|
264
|
+
.ProseMirror-prompt input[type='text'] {
|
265
|
+
padding: 0 4px;
|
266
|
+
}
|
267
|
+
|
268
|
+
.ProseMirror-prompt-close {
|
269
|
+
position: absolute;
|
270
|
+
left: 2px;
|
271
|
+
top: 1px;
|
272
|
+
color: #666;
|
273
|
+
border: none;
|
274
|
+
background: transparent;
|
275
|
+
padding: 0;
|
276
|
+
}
|
277
|
+
|
278
|
+
.ProseMirror-prompt-close:after {
|
279
|
+
content: '✕';
|
280
|
+
font-size: 12px;
|
281
|
+
}
|
282
|
+
|
283
|
+
.ProseMirror-invalid {
|
284
|
+
background: #ffc;
|
285
|
+
border: 1px solid #cc7;
|
286
|
+
border-radius: 4px;
|
287
|
+
padding: 5px 10px;
|
288
|
+
position: absolute;
|
289
|
+
min-width: 10em;
|
290
|
+
}
|
291
|
+
|
292
|
+
.ProseMirror-prompt-buttons {
|
293
|
+
margin-top: 5px;
|
294
|
+
display: none;
|
295
|
+
}
|
296
|
+
:root {
|
297
|
+
--validation-color: #3dcde6;
|
298
|
+
--validation-color-hover: #3dcde624;
|
299
|
+
--validation-gray: #a0a0a0;
|
300
|
+
--validation-debug-color-dirty: #f7a85e66;
|
301
|
+
--validation-debug-color-inflight: #f7a85ea1;
|
302
|
+
}
|
303
|
+
|
304
|
+
.Button {
|
305
|
+
padding: 1px 4px;
|
306
|
+
border: 1px solid lightgrey;
|
307
|
+
border-radius: 3px;
|
308
|
+
font-size: 16px;
|
309
|
+
cursor: pointer;
|
310
|
+
}
|
311
|
+
|
312
|
+
.Button:hover {
|
313
|
+
background-color: #eee;
|
314
|
+
}
|
315
|
+
|
316
|
+
.Input[type='checkbox'] {
|
317
|
+
margin-left: calc(var(--gutter-width));
|
318
|
+
}
|
319
|
+
|
320
|
+
.Button:active,
|
321
|
+
.Button:focus {
|
322
|
+
outline: none;
|
323
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
.tooltip-arrow,
|
2
|
+
.tooltip-arrow::before {
|
3
|
+
position: absolute;
|
4
|
+
width: 8px;
|
5
|
+
height: 8px;
|
6
|
+
background: inherit;
|
7
|
+
}
|
8
|
+
|
9
|
+
.tooltip-arrow {
|
10
|
+
visibility: hidden;
|
11
|
+
}
|
12
|
+
|
13
|
+
tooltip[data-tooltip-show] .tooltip-arrow::before {
|
14
|
+
visibility: visible;
|
15
|
+
content: '';
|
16
|
+
transform: rotate(45deg);
|
17
|
+
}
|
18
|
+
|
19
|
+
tooltip[data-popper-placement^='top'][data-tooltip-show] > .tooltip-arrow {
|
20
|
+
bottom: -4px;
|
21
|
+
}
|
22
|
+
|
23
|
+
tooltip[data-popper-placement^='bottom'] > .tooltip-arrow {
|
24
|
+
top: -4px;
|
25
|
+
}
|
26
|
+
|
27
|
+
tooltip[data-popper-placement^='left'] > .tooltip-arrow {
|
28
|
+
right: -4px;
|
29
|
+
}
|
30
|
+
|
31
|
+
tooltip[data-popper-placement^='right'] > .tooltip-arrow {
|
32
|
+
left: -4px;
|
33
|
+
}
|
34
|
+
|
35
|
+
tooltip[data-tooltip-show] {
|
36
|
+
display: block;
|
37
|
+
}
|
@@ -0,0 +1,96 @@
|
|
1
|
+
import {Controller} from '@hotwired/stimulus'
|
2
|
+
import {html} from 'lit-html'
|
3
|
+
import type {TemplateResult} from 'lit-html'
|
4
|
+
|
5
|
+
type HTMLFormField = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
|
6
|
+
|
7
|
+
export default class AriadneFormWith extends Controller {
|
8
|
+
static targets = ['formField']
|
9
|
+
declare readonly formFieldTargets: [HTMLFormField]
|
10
|
+
|
11
|
+
connect() {
|
12
|
+
this.element.setAttribute('novalidate', 'true')
|
13
|
+
this.element.addEventListener('blur', this.onBlur, true)
|
14
|
+
this.element.addEventListener('submit', this.onSubmit)
|
15
|
+
this.element.addEventListener('ajax:beforeSend', this.onSubmit)
|
16
|
+
}
|
17
|
+
|
18
|
+
disconnect() {
|
19
|
+
this.element.removeEventListener('blur', this.onBlur)
|
20
|
+
this.element.removeEventListener('submit', this.onSubmit)
|
21
|
+
this.element.removeEventListener('ajax:beforeSend', this.onSubmit)
|
22
|
+
}
|
23
|
+
|
24
|
+
onBlur = (event: Event) => {
|
25
|
+
this.validateField(event.target as HTMLFormField)
|
26
|
+
}
|
27
|
+
|
28
|
+
onSubmit = (event: Event) => {
|
29
|
+
if (!this.validateForm()) {
|
30
|
+
event.preventDefault()
|
31
|
+
this.firstInvalidField?.focus()
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
validateForm() {
|
36
|
+
let isValid = true
|
37
|
+
// Not using `find` because we want to validate all the fields
|
38
|
+
for (const field of this.formFields) {
|
39
|
+
if (this.shouldValidateField(field) && !this.validateField(field)) isValid = false
|
40
|
+
}
|
41
|
+
return isValid
|
42
|
+
}
|
43
|
+
|
44
|
+
validateField(field: HTMLFormField) {
|
45
|
+
if (!this.shouldValidateField(field)) return true
|
46
|
+
const isValid = field.checkValidity()
|
47
|
+
field.classList.toggle('invalid', !isValid)
|
48
|
+
this.refreshErrorForInvalidField(field, isValid)
|
49
|
+
return isValid
|
50
|
+
}
|
51
|
+
|
52
|
+
shouldValidateField(field: HTMLFormField) {
|
53
|
+
return (
|
54
|
+
!field.disabled &&
|
55
|
+
!field.classList.contains('ProseMirror') &&
|
56
|
+
!['file', 'reset', 'submit', 'button'].includes(field.type)
|
57
|
+
)
|
58
|
+
}
|
59
|
+
|
60
|
+
refreshErrorForInvalidField(field: HTMLFormField, isValid: boolean) {
|
61
|
+
this.removeExistingErrorMessage(field)
|
62
|
+
if (!isValid) this.showErrorForInvalidField(field)
|
63
|
+
}
|
64
|
+
|
65
|
+
removeExistingErrorMessage(field: HTMLFormField) {
|
66
|
+
const fieldContainer = field.closest('.field')
|
67
|
+
if (!fieldContainer) return
|
68
|
+
const existingErrorMessageElement = fieldContainer.querySelector('.error')
|
69
|
+
if (existingErrorMessageElement) {
|
70
|
+
existingErrorMessageElement?.parentNode?.removeChild(existingErrorMessageElement)
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
showErrorForInvalidField(field: HTMLFormField) {
|
75
|
+
field.insertAdjacentHTML('afterend', this.buildFieldErrorHtml(field))
|
76
|
+
}
|
77
|
+
|
78
|
+
buildFieldErrorHtml(field: HTMLFormField) {
|
79
|
+
const data = html`<p class="error">${field.validationMessage}</p>`
|
80
|
+
return this.getRenderString(data)
|
81
|
+
}
|
82
|
+
|
83
|
+
get formFields(): HTMLFormField[] {
|
84
|
+
return Array.from(this.formFieldTargets)
|
85
|
+
}
|
86
|
+
|
87
|
+
get firstInvalidField() {
|
88
|
+
return this.formFields.find(field => !field.checkValidity())
|
89
|
+
}
|
90
|
+
|
91
|
+
getRenderString = (data: TemplateResult): string => {
|
92
|
+
const {strings, values} = data
|
93
|
+
const v = [...values, ''].map(e => (typeof e === 'object' ? this.getRenderString(e as TemplateResult) : e))
|
94
|
+
return strings.reduce((acc, s, i) => acc + s + v[i], '')
|
95
|
+
}
|
96
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import {Application} from '@hotwired/stimulus'
|
2
|
+
|
3
|
+
import AriadneForm from './ariadne-form'
|
4
|
+
|
5
|
+
import ClipboardCopyComponent from './clipboard-copy-component'
|
6
|
+
import CommentComponent from './comment-component'
|
7
|
+
import RichTextAreaComponent from './rich-text-area-component'
|
8
|
+
import SlideoverComponent from './slideover-component'
|
9
|
+
import TooltipComponent from './tooltip-component'
|
10
|
+
|
11
|
+
import './time-ago-component'
|
12
|
+
|
13
|
+
const application = Application.start()
|
14
|
+
|
15
|
+
application.register('clipboard-copy-component', ClipboardCopyComponent)
|
16
|
+
application.register('ariadne-form', AriadneForm)
|
17
|
+
application.register('comment-component', CommentComponent)
|
18
|
+
application.register('rich-text-area-component', RichTextAreaComponent)
|
19
|
+
application.register('slideover-component', SlideoverComponent)
|
20
|
+
application.register('tooltip-component', TooltipComponent)
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ariadne
|
4
|
+
# Use `BaseButton` to render an unstyled `<button>` tag that can be customized.
|
5
|
+
class BaseButton < Ariadne::Component
|
6
|
+
DEFAULT_TAG = :button
|
7
|
+
TAG_OPTIONS = [DEFAULT_TAG, :a, :summary].freeze
|
8
|
+
|
9
|
+
DEFAULT_TYPE = :button
|
10
|
+
TYPE_SUBMIT = :submit
|
11
|
+
TYPE_OPTIONS = [DEFAULT_TYPE, :reset, TYPE_SUBMIT].freeze
|
12
|
+
|
13
|
+
SIZE_CLASS_MAPPINGS = {
|
14
|
+
xs: "ariadne-px-2.5 ariadne-py-1.5 ariadne-text-xs ariadne-font-medium ariadne-rounded",
|
15
|
+
sm: "ariadne-px-3 ariadne-py-2 ariadne-text-sm ariadne-leading-4 ariadne-font-medium ariadne-rounded-m",
|
16
|
+
md: "ariadne-px-4 ariadne-py-2 ariadne-text-sm ariadne-font-medium ariadne-rounded-md",
|
17
|
+
lg: "ariadne-px-4 ariadne-py-2 ariadne-text-base ariadne-font-medium ariadne-rounded-md",
|
18
|
+
xl: "ariadne-px-6 ariadne-py-3 ariadne-text-base ariadne-font-medium ariadne-rounded-md",
|
19
|
+
}.freeze
|
20
|
+
VALID_SIZES = SIZE_CLASS_MAPPINGS.keys.freeze
|
21
|
+
|
22
|
+
DEFAULT_CLASSES = "ariadne-inline-flex ariadne-items-center ariadne-border ariadne-shadow-sm focus:ariadne-outline-none focus:ariadne-ring-2 focus:ariadne-ring-offset-2"
|
23
|
+
|
24
|
+
DEFAULT_SIZE = :md
|
25
|
+
|
26
|
+
# @example Setting the size
|
27
|
+
# <%= render(Ariadne::BaseButton.new(size: :xs)) { "I am an extra small button!" } %>
|
28
|
+
# <%= render(Ariadne::BaseButton.new(size: :sm)) { "I am a small button!" } %>
|
29
|
+
# <%= render(Ariadne::BaseButton.new(size: :md)) { "I am a medium button!" } %>
|
30
|
+
# <%= render(Ariadne::BaseButton.new(size: :lg)) { "I am a large button!" } %>
|
31
|
+
# <%= render(Ariadne::BaseButton.new(size: :xl)) { "I am an extra large button!" } %>
|
32
|
+
#
|
33
|
+
# @param tag [Symbol] <%= one_of(Ariadne::BaseButton::TAG_OPTIONS) %>
|
34
|
+
# @param type [Symbol] <%= one_of(Ariadne::BaseButton::TYPE_OPTIONS) %>
|
35
|
+
# @param size [Symbol] <%= one_of(Ariadne::BaseButton::VALID_SIZES) %>
|
36
|
+
# @param classes [String] <%= link_to_classes_docs %>
|
37
|
+
# @param attributes [Hash] <%= link_to_attributes_docs %>
|
38
|
+
def initialize(
|
39
|
+
tag: DEFAULT_TAG,
|
40
|
+
type: DEFAULT_TYPE,
|
41
|
+
size: DEFAULT_SIZE,
|
42
|
+
classes: "",
|
43
|
+
attributes: {}
|
44
|
+
)
|
45
|
+
@attributes = attributes
|
46
|
+
@tag = fetch_or_raise(TAG_OPTIONS, tag)
|
47
|
+
@size = fetch_or_raise(VALID_SIZES, size)
|
48
|
+
|
49
|
+
@attributes[:type] = fetch_or_raise(TYPE_OPTIONS, type) if button?
|
50
|
+
@classes = class_names(DEFAULT_CLASSES, SIZE_CLASS_MAPPINGS[@size], classes)
|
51
|
+
end
|
52
|
+
|
53
|
+
def call
|
54
|
+
render(Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes)) { content }
|
55
|
+
end
|
56
|
+
|
57
|
+
private def button?
|
58
|
+
@tag == :button
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ariadne
|
4
|
+
# All Ariadne ViewComponents accept a standard set of options: classes, which match Tailwind CSS classes, and attributes, which match HTML attributes..
|
5
|
+
#
|
6
|
+
# Under the hood, any-non class attributes is passed to Rails' [`tag`](https://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-tag)
|
7
|
+
# (for self-closing tags) or [`content_tag`](https://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-content_tag).
|
8
|
+
class BaseComponent < Ariadne::Component
|
9
|
+
SELF_CLOSING_TAGS = [:area, :base, :br, :col, :embed, :hr, :img, :input, :link, :meta, :param, :source, :track, :wbr].freeze
|
10
|
+
|
11
|
+
def initialize(tag:, classes: "", attributes: {})
|
12
|
+
@tag = tag
|
13
|
+
|
14
|
+
@attributes = validate_attributes(tag: tag, attributes: attributes) || {}
|
15
|
+
@attributes[:"data-ariadne-view-component"] = true
|
16
|
+
|
17
|
+
classes = @attributes.fetch(:classes, "") if classes.blank?
|
18
|
+
@classes = validate_class_names(classes) || {}
|
19
|
+
@content_tag_args = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def call
|
23
|
+
options = @attributes.merge(@classes)
|
24
|
+
if SELF_CLOSING_TAGS.include?(@tag)
|
25
|
+
tag(@tag, options)
|
26
|
+
else
|
27
|
+
content_tag(@tag, content, options)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private def validate_class_names(classes)
|
32
|
+
return if classes.blank?
|
33
|
+
|
34
|
+
{ class: Ariadne::ViewComponents.tailwind_merger.merge(classes) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<%= render Ariadne::NarrowContainerComponent.new do %>
|
2
|
+
<%= render Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes) do %>
|
3
|
+
<% if icon.present? %>
|
4
|
+
<%= icon %>
|
5
|
+
<% elsif image.present? %>
|
6
|
+
<%= image %>
|
7
|
+
<% end %>
|
8
|
+
<%= heading %>
|
9
|
+
<% if description.present? %>
|
10
|
+
<%= description %>
|
11
|
+
<% end %>
|
12
|
+
<%= content %>
|
13
|
+
<div class="ariadne-mt-8 ariadne-flex ariadne-justify-center">
|
14
|
+
<% if primary_action.present? %>
|
15
|
+
<div class="ariadne-inline-flex ariadne-rounded-md shadow">
|
16
|
+
<%= primary_action %>
|
17
|
+
</div>
|
18
|
+
<% end %>
|
19
|
+
<% if secondary_action.present? %>
|
20
|
+
<div class="ariadne-ml-3 ariadne-inline-flex">
|
21
|
+
<%= secondary_action %>
|
22
|
+
</div>
|
23
|
+
<% end %>
|
24
|
+
</div>
|
25
|
+
<% end %>
|
26
|
+
<% end %>
|