ariadne_view_components 0.0.80.3 → 0.0.82
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/CHANGELOG.md +13 -0
- data/app/assets/javascripts/ariadne_view_components.js +14 -14
- data/app/assets/javascripts/ariadne_view_components.js.br +0 -0
- data/app/assets/javascripts/ariadne_view_components.js.gz +0 -0
- data/app/assets/javascripts/ariadne_view_components.js.map +1 -1
- data/app/assets/stylesheets/ariadne_view_components.css +1 -1
- data/app/assets/stylesheets/ariadne_view_components.css.br +0 -0
- data/app/assets/stylesheets/ariadne_view_components.css.gz +0 -0
- data/app/components/ariadne/base_component.rb +5 -1
- data/app/components/ariadne/form/checkbox/component.html.erb +21 -5
- data/app/components/ariadne/form/checkbox/component.rb +36 -0
- data/app/components/ariadne/form/group/component.html.erb +0 -2
- data/app/components/ariadne/form/group/component.rb +4 -1
- data/app/components/ariadne/form/text_field/component.rb +26 -23
- data/app/components/ariadne/ui/badge/component.rb +12 -17
- data/app/components/ariadne/ui/button/component.rb +1 -0
- data/app/components/ariadne/ui/combobox/component.html.erb +5 -17
- data/app/components/ariadne/ui/combobox/component.rb +8 -28
- data/app/components/ariadne/ui/combobox/component.ts +24 -39
- data/app/components/ariadne/ui/dialog/component.rb +18 -2
- data/app/components/ariadne/ui/flash/component.html.erb +11 -11
- data/app/components/ariadne/ui/flash/component.rb +30 -12
- data/app/components/ariadne/ui/link/component.rb +21 -5
- data/app/components/ariadne/ui/list/component.html.erb +28 -4
- data/app/components/ariadne/ui/list/component.rb +119 -1
- data/app/components/ariadne/ui/list/component.ts +57 -0
- data/app/components/ariadne/ui/popover/component.html.erb +4 -4
- data/app/components/ariadne/ui/popover/component.rb +3 -1
- data/app/components/ariadne/ui/popover/component.ts +1 -1
- data/app/components/ariadne/ui/typography/component.rb +19 -0
- data/app/frontend/ariadne/stimulus_app.ts +2 -2
- data/app/frontend/controllers/{autosubmittable_controller.ts → form_autosubmit_controller.ts} +1 -2
- data/app/lib/ariadne/view_component/style_variants.rb +50 -0
- data/lib/ariadne/forms/dsl/badge.rb +2 -2
- data/lib/ariadne/forms/dsl/button_input.rb +2 -1
- data/lib/ariadne/forms/dsl/clipboard_copy_button.rb +34 -0
- data/lib/ariadne/forms/dsl/input_methods.rb +4 -0
- data/lib/ariadne/view_components/version.rb +1 -1
- metadata +5 -9
- data/app/components/ariadne/ui/combobox/item/component.html.erb +0 -9
- data/app/components/ariadne/ui/combobox/item/component.rb +0 -61
- data/app/components/ariadne/ui/combobox/option/component.html.erb +0 -11
- data/app/components/ariadne/ui/combobox/option/component.rb +0 -44
- data/app/components/ariadne/ui/list/item/component.html.erb +0 -16
- data/app/components/ariadne/ui/list/item/component.rb +0 -17
@@ -1,13 +1,14 @@
|
|
1
1
|
import {type Placement, autoUpdate, computePosition, flip, offset, shift, size} from '@floating-ui/dom'
|
2
|
+
import DetailsMenuElement from '@github/details-menu-element'
|
2
3
|
import {controllerFactory} from '@utils/createController'
|
3
4
|
import {useClickOutside, useMutation} from 'stimulus-use'
|
4
5
|
|
5
6
|
export default class ComboboxController extends controllerFactory<HTMLDetailsElement>()({
|
6
7
|
targets: {
|
7
|
-
|
8
|
-
|
9
|
-
popover:
|
10
|
-
|
8
|
+
wrapper: HTMLDetailsElement,
|
9
|
+
button: HTMLElement,
|
10
|
+
popover: DetailsMenuElement,
|
11
|
+
options: HTMLDivElement,
|
11
12
|
},
|
12
13
|
values: {
|
13
14
|
clamped: Boolean,
|
@@ -15,35 +16,8 @@ export default class ComboboxController extends controllerFactory<HTMLDetailsEle
|
|
15
16
|
},
|
16
17
|
}) {
|
17
18
|
private changedIds = new Set<string>()
|
18
|
-
private clickHandlers: Array<() => void> = []
|
19
|
-
labels: Array<{el: HTMLLabelElement; searchString: string}>
|
20
19
|
unsubAutoUpdate: (() => void) | undefined
|
21
20
|
|
22
|
-
private setupClickHandlers() {
|
23
|
-
const cb = () => this.toggle()
|
24
|
-
|
25
|
-
for (const fn of this.clickHandlers) {
|
26
|
-
fn()
|
27
|
-
}
|
28
|
-
this.clickHandlers = []
|
29
|
-
|
30
|
-
for (const el of this.anchorTarget.querySelectorAll('button, [tabindex]:not([tabindex="-1"])')) {
|
31
|
-
el.addEventListener('click', cb)
|
32
|
-
this.clickHandlers.push(() => el.removeEventListener('click', cb))
|
33
|
-
}
|
34
|
-
}
|
35
|
-
|
36
|
-
checkboxClicked(e: Event) {
|
37
|
-
const target = e.target as HTMLInputElement
|
38
|
-
const value = target.value
|
39
|
-
if (this.changedIds.has(value)) {
|
40
|
-
this.changedIds.delete(value)
|
41
|
-
} else {
|
42
|
-
this.changedIds.add(value)
|
43
|
-
}
|
44
|
-
this.dispatch('clicked', {detail: value})
|
45
|
-
}
|
46
|
-
|
47
21
|
clickOutside() {
|
48
22
|
this.element.open = false
|
49
23
|
this.setupAutoUpdate()
|
@@ -51,7 +25,6 @@ export default class ComboboxController extends controllerFactory<HTMLDetailsEle
|
|
51
25
|
}
|
52
26
|
|
53
27
|
close() {
|
54
|
-
if (this.hasSearchInputTarget) this.searchInputTarget.value = ''
|
55
28
|
if (this.changedIds.size > 0) {
|
56
29
|
this.dispatch('changed')
|
57
30
|
this.changedIds.clear()
|
@@ -62,13 +35,28 @@ export default class ComboboxController extends controllerFactory<HTMLDetailsEle
|
|
62
35
|
useClickOutside(this)
|
63
36
|
useMutation(this, {childList: true, subtree: true})
|
64
37
|
this.setupAutoUpdate()
|
65
|
-
this.
|
38
|
+
this.setupForm()
|
66
39
|
}
|
67
40
|
|
68
41
|
disconnect() {
|
69
42
|
this.unsubAutoUpdate?.()
|
70
43
|
}
|
71
44
|
|
45
|
+
setupForm(): void {
|
46
|
+
// https://github.com/github/details-menu-element?tab=readme-ov-file#markup
|
47
|
+
for (const checkbox of this.popoverTarget.querySelectorAll('input[type="checkbox"]')) {
|
48
|
+
checkbox.addEventListener('change', (e: {target: HTMLInputElement}) => {
|
49
|
+
const value = e.target as HTMLInputElement
|
50
|
+
if (this.changedIds.has(value)) {
|
51
|
+
this.changedIds.delete(value)
|
52
|
+
} else {
|
53
|
+
this.changedIds.add(value)
|
54
|
+
}
|
55
|
+
this.dispatch('clicked', {detail: value})
|
56
|
+
})
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
72
60
|
setupAutoUpdate(): void {
|
73
61
|
if (!this.element.open) {
|
74
62
|
this.unsubAutoUpdate?.()
|
@@ -77,19 +65,16 @@ export default class ComboboxController extends controllerFactory<HTMLDetailsEle
|
|
77
65
|
|
78
66
|
const updatePopoverPosition = (): void => {
|
79
67
|
const options = this.optionsTarget
|
80
|
-
const searchInput = this.hasSearchInputTarget ? this.searchInputTarget : null
|
81
68
|
const shouldClamp = this.clampedValue
|
82
69
|
|
83
|
-
void computePosition(this.
|
70
|
+
void computePosition(this.buttonTarget, this.popoverTarget, {
|
84
71
|
middleware: [
|
85
72
|
offset(6),
|
86
73
|
flip(),
|
87
74
|
shift({padding: 6}),
|
88
75
|
size({
|
89
76
|
apply({availableHeight}) {
|
90
|
-
|
91
|
-
|
92
|
-
let maxHeight = availableHeight - inputHeight - 6
|
77
|
+
let maxHeight = availableHeight - 6
|
93
78
|
if (shouldClamp && maxHeight > 400) maxHeight = 400
|
94
79
|
|
95
80
|
Object.assign(options.style, {
|
@@ -109,7 +94,7 @@ export default class ComboboxController extends controllerFactory<HTMLDetailsEle
|
|
109
94
|
}
|
110
95
|
|
111
96
|
updatePopoverPosition()
|
112
|
-
this.unsubAutoUpdate = autoUpdate(this.
|
97
|
+
this.unsubAutoUpdate = autoUpdate(this.buttonTarget, this.popoverTarget, updatePopoverPosition)
|
113
98
|
}
|
114
99
|
|
115
100
|
toggle(): void {
|
@@ -8,6 +8,7 @@ module Ariadne
|
|
8
8
|
option :title
|
9
9
|
option :trigger_close_label
|
10
10
|
option :description, optional: true
|
11
|
+
option :width, default: proc { :base }
|
11
12
|
|
12
13
|
renders_one :trigger
|
13
14
|
renders_one :footer
|
@@ -18,8 +19,6 @@ module Ariadne
|
|
18
19
|
base do
|
19
20
|
[
|
20
21
|
"ariadne-fixed",
|
21
|
-
"ariadne-w-96",
|
22
|
-
"ariadne-max-w-[90vw]",
|
23
22
|
"ariadne-max-h-[90-vh]",
|
24
23
|
"ariadne-shadow-xl",
|
25
24
|
"ariadne-rounded-2xl",
|
@@ -31,6 +30,23 @@ module Ariadne
|
|
31
30
|
"backdrop:dark:ariadne-bg-zinc-100/20",
|
32
31
|
]
|
33
32
|
end
|
33
|
+
variants do
|
34
|
+
width do
|
35
|
+
base do
|
36
|
+
[
|
37
|
+
"ariadne-w-96",
|
38
|
+
"ariadne-max-w-[90vw]",
|
39
|
+
]
|
40
|
+
end
|
41
|
+
|
42
|
+
wide do
|
43
|
+
[
|
44
|
+
"ariadne-w-3/5",
|
45
|
+
"ariadne-max-w-[90vw]",
|
46
|
+
]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
34
50
|
end
|
35
51
|
end
|
36
52
|
end
|
@@ -1,18 +1,18 @@
|
|
1
1
|
<div class="<%= html_attrs[:class] %>" <%= html_attributes %>>
|
2
|
-
<div class="ariadne-p-4">
|
2
|
+
<div class="ariadne-p-4">
|
3
3
|
<div class="ariadne-flex ariadne-items-start">
|
4
|
-
|
4
|
+
<div class="ariadne-flex-shrink-0 <%= style(:text, type:) %>">
|
5
5
|
<%= icon %>
|
6
|
-
|
7
|
-
|
8
|
-
<p class="ariadne-text-sm ariadne-font-semibold "><%= title %></p>
|
9
|
-
<p class="ariadne-mt-1 ariadne-text-sm "><%= message %></p>
|
10
|
-
|
11
|
-
|
6
|
+
</div>
|
7
|
+
<div class="ariadne-ml-3 ariadne-w-0 ariadne-flex-1 ariadne-pt-0.5 <%= style(:text, type:) %>">
|
8
|
+
<p class="ariadne-text-sm ariadne-font-semibold" data-flash-target="title"><%= title %></p>
|
9
|
+
<p class="ariadne-mt-1 ariadne-text-sm" data-flash-target="message"><%= message %></p>
|
10
|
+
</div>
|
11
|
+
<div class="ariadne-ml-4 ariadne-flex ariadne-flex-shrink-0 ">
|
12
12
|
<% if dismissable? %>
|
13
|
-
|
13
|
+
<%= render Ariadne::UI::Button::Component.new(theme: :nude, html_attrs: { class: style(:dismissable, type:), aria: { label: "close_label" }, data: { action: "click->#{stimulus_name}#hide" } }).as_icon(icon: "x-mark", variant: :outline) %>
|
14
14
|
<% end %>
|
15
|
+
</div>
|
15
16
|
</div>
|
16
|
-
|
17
|
-
</div>
|
17
|
+
</div>
|
18
18
|
</div>
|
@@ -9,20 +9,25 @@ module Ariadne
|
|
9
9
|
option :dismissible, default: proc { false }
|
10
10
|
option :title
|
11
11
|
option :message
|
12
|
+
option :persist, default: proc { false }
|
13
|
+
option :width, default: proc { :base }
|
12
14
|
|
13
15
|
accepts_html_attributes do |html_attrs|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
16
|
+
unless persist
|
17
|
+
html_attrs[:data] = {
|
18
|
+
controller: "flash",
|
19
|
+
transition_enter: "ariadne-transform ariadne-ease-out ariadne-duration-300 ariadne-transition-all",
|
20
|
+
transition_enter_start: "ariadne-translate-y-2 ariadne-opacity-0 sm:ariadne-translate-y-0 sm:ariadne-translate-x-2",
|
21
|
+
transition_enter_end: "ariadne-translate-y-0 ariadne-opacity-100 sm:ariadne-translate-x-0",
|
22
|
+
transition_leave: "ariadne-transition-all ariadne-ease-in ariadne-duration-100",
|
23
|
+
transition_leave_start: "ariadne-opacity-100",
|
24
|
+
transition_leave_end: "ariadne-opacity-0",
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
23
28
|
html_attrs[:class] = Ariadne::ViewComponents.tailwind_merger.merge([
|
24
29
|
html_attrs[:class],
|
25
|
-
style(type:),
|
30
|
+
style(type:, width:),
|
26
31
|
])
|
27
32
|
end
|
28
33
|
|
@@ -36,8 +41,6 @@ module Ariadne
|
|
36
41
|
base do
|
37
42
|
[
|
38
43
|
"ariadne-pointer-events-auto",
|
39
|
-
"ariadne-w-full",
|
40
|
-
"ariadne-max-w-sm",
|
41
44
|
"ariadne-overflow-hidden",
|
42
45
|
"ariadne-rounded-lg",
|
43
46
|
"ariadne-shadow-lg",
|
@@ -49,6 +52,21 @@ module Ariadne
|
|
49
52
|
end
|
50
53
|
|
51
54
|
variants do
|
55
|
+
width do
|
56
|
+
base do
|
57
|
+
[
|
58
|
+
"ariadne-w-full",
|
59
|
+
"ariadne-max-w-sm",
|
60
|
+
]
|
61
|
+
end
|
62
|
+
|
63
|
+
full do
|
64
|
+
[
|
65
|
+
"ariadne-w-full",
|
66
|
+
]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
52
70
|
type do
|
53
71
|
danger do
|
54
72
|
[
|
@@ -32,20 +32,36 @@ module Ariadne
|
|
32
32
|
theme do
|
33
33
|
base do
|
34
34
|
[
|
35
|
+
"ariadne-text-indigo-600",
|
36
|
+
"dark:ariadne-text-indigo-400",
|
37
|
+
|
35
38
|
"[&>svg]:ariadne-text-zinc-400",
|
36
39
|
"[&>svg]:dark:ariadne-text-zinc-600",
|
37
|
-
|
38
|
-
"
|
40
|
+
|
41
|
+
"hover:ariadne-text-indigo-500",
|
42
|
+
"dark:hover:ariadne-text-indigo-300",
|
43
|
+
"hover:ariadne-border-indigo-500",
|
44
|
+
"dark:hover:ariadne-border-indigo-300",
|
45
|
+
"focus:ariadne-text-indigo-500",
|
46
|
+
"dark:focus:ariadne-text-indigo-300",
|
47
|
+
"focus:!ariadne-border-transparent",
|
48
|
+
"active:ariadne-bg-indigo-700/10",
|
49
|
+
"active:dark:ariadne-bg-indigo-300/10",
|
50
|
+
]
|
51
|
+
end
|
52
|
+
|
53
|
+
nude do
|
54
|
+
[
|
39
55
|
"hover:ariadne-border-indigo-600",
|
40
56
|
"dark:hover:ariadne-border-indigo-400",
|
41
|
-
"focus:ariadne-text-indigo-
|
42
|
-
"dark:focus:ariadne-text-indigo-
|
57
|
+
"focus:ariadne-text-indigo-500",
|
58
|
+
"dark:focus:ariadne-text-indigo-300",
|
43
59
|
"focus:!ariadne-border-transparent",
|
44
60
|
"active:ariadne-bg-indigo-700/10",
|
45
61
|
"active:dark:ariadne-bg-indigo-300/10",
|
46
62
|
]
|
47
63
|
end
|
48
|
-
|
64
|
+
|
49
65
|
thick { "ariadne-font-semibold" }
|
50
66
|
end
|
51
67
|
size do
|
@@ -1,6 +1,30 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
<div class="<%= html_attrs[:class] %>" <%= html_attributes %>>
|
2
|
+
<% if filter_field? %>
|
3
|
+
<div class="ariadne-pb-1.5 ariadne-px-1">
|
4
|
+
<%= render filter_field %>
|
5
|
+
</div>
|
6
|
+
<% end %>
|
7
|
+
<div class="<%= style(:items) %>">
|
8
|
+
<% links.each do |link| %>
|
9
|
+
<div class="" role="menuitem"><%= link %></div>
|
10
|
+
<% end %>
|
11
|
+
<% checkboxes.each do |checkbox| %>
|
12
|
+
<div
|
13
|
+
class="<%= style(:item) %>"
|
14
|
+
data-<%= stimulus_name %>-target="searchString">
|
15
|
+
<div class="ariadne-truncate" role="menuitemcheckbox"><%= checkbox %></div>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
3
18
|
<% items.each do |item| %>
|
4
|
-
|
19
|
+
<div
|
20
|
+
<%= 'role="menuitem"' if as_menu %>
|
21
|
+
class="<%= style(:item) %>"
|
22
|
+
data-<%= stimulus_name %>-target="searchString">
|
23
|
+
<div class="ariadne-relative ariadne-flex ariadne-cursor-default ariadne-select-none ariadne-items-center ariadne-rounded-sm ariadne-px-2 ariadne-py-1.5 ariadne-text-sm ariadne-outline-none ariadne-data-[disabled=true]:pointer-events-none ariadne-data-[selected=true]:bg-accent ariadne-data-[selected=true]:text-accent-foreground data-[disabled=true]:ariadne-opacity-50"><%= item %></div>
|
24
|
+
</div>
|
5
25
|
<% end %>
|
6
|
-
|
26
|
+
<div class="ariadne-text-center ariadne-hidden" data-<%= stimulus_name %>-target="emptyRoot">
|
27
|
+
<span class="ariadne-py-3 ariadne-text-md ariadne-text-zinc-600 dark:ariadne-text-zinc-400"><%= @empty_placeholder %> </span>
|
28
|
+
</div>
|
29
|
+
</div>
|
30
|
+
</div>
|
@@ -5,7 +5,125 @@ module Ariadne
|
|
5
5
|
module UI
|
6
6
|
module List
|
7
7
|
class Component < Ariadne::BaseComponent
|
8
|
-
|
8
|
+
option :as_menu, default: proc { false }
|
9
|
+
|
10
|
+
option :size, default: proc { :md }
|
11
|
+
|
12
|
+
renders_one :filter_field, lambda { |**options|
|
13
|
+
raise ArgumentError, "Must provide text for `empty_placeholder`" if options[:empty_placeholder].blank?
|
14
|
+
|
15
|
+
@empty_placeholder = options.delete(:empty_placeholder)
|
16
|
+
|
17
|
+
options.delete(:size)
|
18
|
+
options[:theme] = :nude
|
19
|
+
options[:width] = :full
|
20
|
+
options[:name] = "search"
|
21
|
+
options[:label] = ""
|
22
|
+
|
23
|
+
options[:html_attrs] ||= {}
|
24
|
+
options[:html_attrs].merge!({
|
25
|
+
autocomplete: "off",
|
26
|
+
autofocus: true,
|
27
|
+
type: "search",
|
28
|
+
data: {
|
29
|
+
"#{stimulus_name}-target": "input",
|
30
|
+
action: "#{stimulus_name}#handleInput",
|
31
|
+
},
|
32
|
+
})
|
33
|
+
|
34
|
+
Ariadne::Form::TextField::Component.new(**options)
|
35
|
+
}
|
36
|
+
|
37
|
+
renders_many :checkboxes, Ariadne::Form::Checkbox::Component
|
38
|
+
renders_many :radio_buttons, Ariadne::Form::RadioButton::Component
|
39
|
+
renders_many :links, lambda { |**options|
|
40
|
+
options[:theme] = :nude
|
41
|
+
options[:"data-#{stimulus_name}-target"] = "searchString"
|
42
|
+
|
43
|
+
options[:html_attrs] ||= {}
|
44
|
+
options[:html_attrs][:class] ||= ""
|
45
|
+
options[:html_attrs][:class] = [
|
46
|
+
"ariadne-truncate",
|
47
|
+
"ariadne-border-b-0",
|
48
|
+
"ariadne-flex",
|
49
|
+
"ariadne-gap-0.5",
|
50
|
+
"ariadne-items-center",
|
51
|
+
"ariadne-ps-2",
|
52
|
+
"ariadne-pe-1",
|
53
|
+
"ariadne-rounded",
|
54
|
+
"!ariadne-ring-0",
|
55
|
+
"hover:ariadne-bg-zinc-100",
|
56
|
+
"hover:dark:ariadne-bg-zinc-800",
|
57
|
+
"focus-within:ariadne-bg-zinc-100",
|
58
|
+
"focus-within:dark:ariadne-bg-zinc-800",
|
59
|
+
"ariadne-cursor-pointer",
|
60
|
+
options[:html_attrs][:class],
|
61
|
+
]
|
62
|
+
|
63
|
+
Ariadne::UI::Link::Component.new(**options)
|
64
|
+
}
|
65
|
+
|
66
|
+
renders_many :items, BaseComponent::ACCEPT_ANYTHING
|
67
|
+
|
68
|
+
accepts_html_attributes do |html_attrs|
|
69
|
+
html_attrs[:class] = Ariadne::ViewComponents.tailwind_merger.merge([style, html_attrs[:class]].join(" "))
|
70
|
+
html_attrs[:data] = {
|
71
|
+
controller: stimulus_name,
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
style do
|
76
|
+
base do
|
77
|
+
[
|
78
|
+
"ariadne-overflow-y-auto",
|
79
|
+
]
|
80
|
+
end
|
81
|
+
|
82
|
+
variants do
|
83
|
+
size do
|
84
|
+
sm { "ariadne-w-36" }
|
85
|
+
md { "ariadne-w-52" }
|
86
|
+
lg { "ariadne-w-96" }
|
87
|
+
full { "ariadne-w-full" }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
style :items do
|
93
|
+
base do
|
94
|
+
[
|
95
|
+
"ariadne-flex",
|
96
|
+
"ariadne-flex-col",
|
97
|
+
"ariadne-grow",
|
98
|
+
]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
style :item do
|
103
|
+
base do
|
104
|
+
[
|
105
|
+
# "ariadne-gap-0.5",
|
106
|
+
"ariadne-items-center",
|
107
|
+
"ariadne-rounded",
|
108
|
+
"!ariadne-ring-0",
|
109
|
+
"hover:ariadne-bg-zinc-100",
|
110
|
+
"hover:dark:ariadne-bg-zinc-800",
|
111
|
+
"focus-within:ariadne-bg-zinc-100",
|
112
|
+
"focus-within:dark:ariadne-bg-zinc-800",
|
113
|
+
"ariadne-cursor-default",
|
114
|
+
"ariadne-select-none",
|
115
|
+
"ariadne-items-center",
|
116
|
+
"ariadne-rounded-sm",
|
117
|
+
"ariadne-px-2",
|
118
|
+
# "ariadne-py-1.5",
|
119
|
+
"ariadne-text-sm",
|
120
|
+
"ariadne-outline-none",
|
121
|
+
"ariadne-transition-colors",
|
122
|
+
"disabled:ariadne-pointer-events-none",
|
123
|
+
"disabled:ariadne-opacity-50",
|
124
|
+
]
|
125
|
+
end
|
126
|
+
end
|
9
127
|
end
|
10
128
|
end
|
11
129
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
import {controllerFactory} from '@utils/createController'
|
2
|
+
import {useIntersection} from 'stimulus-use'
|
3
|
+
|
4
|
+
export default class InputFilterController extends controllerFactory()({
|
5
|
+
targets: {
|
6
|
+
emptyRoot: null,
|
7
|
+
input: HTMLInputElement,
|
8
|
+
searchString: null,
|
9
|
+
},
|
10
|
+
}) {
|
11
|
+
private items: {el: HTMLElement; searchString: string}[]
|
12
|
+
|
13
|
+
private handleNewQuery(query: string) {
|
14
|
+
let foundSomething = false
|
15
|
+
|
16
|
+
for (const {el, searchString} of this.items) {
|
17
|
+
const contains = searchString.includes(query.trim().toLowerCase())
|
18
|
+
|
19
|
+
if (!foundSomething && contains) foundSomething = true
|
20
|
+
|
21
|
+
if (contains) {
|
22
|
+
el.classList.remove('ariadne-hidden')
|
23
|
+
} else {
|
24
|
+
el.classList.add('ariadne-hidden')
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
if (foundSomething) {
|
29
|
+
this.emptyRootTarget.classList.add('ariadne-hidden')
|
30
|
+
} else {
|
31
|
+
this.emptyRootTarget.classList.remove('ariadne-hidden')
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
connect() {
|
36
|
+
this.items = this.searchStringTargets.map((el: HTMLElement) => {
|
37
|
+
return {
|
38
|
+
el,
|
39
|
+
searchString: (el.textContent ?? '').trim().toLowerCase(),
|
40
|
+
}
|
41
|
+
})
|
42
|
+
useIntersection(this)
|
43
|
+
}
|
44
|
+
|
45
|
+
appear(entry, observer) {
|
46
|
+
this.reset()
|
47
|
+
}
|
48
|
+
|
49
|
+
handleInput() {
|
50
|
+
if (this.hasSearchStringTarget) this.handleNewQuery(this.inputTarget.value)
|
51
|
+
}
|
52
|
+
|
53
|
+
reset() {
|
54
|
+
this.handleNewQuery('')
|
55
|
+
if (this.hasInputTarget) this.inputTarget.value = ''
|
56
|
+
}
|
57
|
+
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<div data-controller="<%= @stimulus_controllers %>">
|
2
|
-
<%= button %>
|
3
|
-
<div class="<%= html_attrs[:class] %>" <%= html_attributes %>>
|
4
|
-
|
5
|
-
</div>
|
2
|
+
<%= button %>
|
3
|
+
<div class="<%= html_attrs[:class] %>" <%= html_attributes %>>
|
4
|
+
<%= content %>
|
5
|
+
</div>
|
6
6
|
</div>
|
@@ -28,7 +28,7 @@ module Ariadne
|
|
28
28
|
|
29
29
|
options[:html_attrs][:data] ||= {}
|
30
30
|
options[:html_attrs][:data] = {
|
31
|
-
"#{stimulus_name}-target" => ["
|
31
|
+
"#{stimulus_name}-target" => ["button", html_attrs.fetch(:data, {}).fetch(:target, nil)].compact.join(" "),
|
32
32
|
}.merge(options[:html_attrs][:data])
|
33
33
|
|
34
34
|
Ariadne::UI::Button::Component.new(**options)
|
@@ -38,6 +38,8 @@ module Ariadne
|
|
38
38
|
html_attrs[:id] ||= target_id
|
39
39
|
html_attrs[:popover] = ""
|
40
40
|
|
41
|
+
html_attrs[:class] = Ariadne::ViewComponents.tailwind_merger.merge([style, html_attrs[:class]].join(" "))
|
42
|
+
|
41
43
|
# requires CSS Anchor Positioning
|
42
44
|
# as a `style` to account for future feature where the popover can be moved
|
43
45
|
# html_attrs[:style] = "inset: unset; top: anchor(--popover-#{target_id} bottom); right: anchor(--popover-#{target_id} left, -1rem);"
|
@@ -24,7 +24,7 @@ export default class PopoverController extends controllerFactory()({
|
|
24
24
|
placement: this.placementValue,
|
25
25
|
middleware: [offset(5), flip(), shift({padding: 5})],
|
26
26
|
}).then(({x, y}) => {
|
27
|
-
Object.assign(this.
|
27
|
+
Object.assign(this.buttonTarget.style, {
|
28
28
|
left: `${x}px`,
|
29
29
|
top: `${y}px`,
|
30
30
|
})
|
@@ -25,8 +25,12 @@ module Ariadne
|
|
25
25
|
:h3
|
26
26
|
when :ann
|
27
27
|
:h4
|
28
|
+
when :label
|
29
|
+
:h5
|
28
30
|
when :lede
|
29
31
|
:p
|
32
|
+
when :text
|
33
|
+
:p
|
30
34
|
when :code
|
31
35
|
:code
|
32
36
|
else
|
@@ -110,6 +114,18 @@ module Ariadne
|
|
110
114
|
]
|
111
115
|
end
|
112
116
|
|
117
|
+
label do
|
118
|
+
[
|
119
|
+
"ariadne-justify-between",
|
120
|
+
"ariadne-whitespace-nowrap",
|
121
|
+
"ariadne-text-sm",
|
122
|
+
"ariadne-font-medium",
|
123
|
+
"ariadne-uppercase",
|
124
|
+
"ariadne-text-zinc-600",
|
125
|
+
"dark:ariadne-text-zinc-400",
|
126
|
+
]
|
127
|
+
end
|
128
|
+
|
113
129
|
code do
|
114
130
|
[
|
115
131
|
"ariadne-relative",
|
@@ -128,6 +144,9 @@ module Ariadne
|
|
128
144
|
"ariadne-text-muted-foreground",
|
129
145
|
]
|
130
146
|
end
|
147
|
+
|
148
|
+
text do
|
149
|
+
end
|
131
150
|
end
|
132
151
|
end
|
133
152
|
end
|
@@ -40,8 +40,8 @@ for (const [path, module] of Object.entries(controllerModules)) {
|
|
40
40
|
const dirs = path.split('/')
|
41
41
|
|
42
42
|
// Dropping ../controllers to end up
|
43
|
-
// with something like "ariadne-
|
44
|
-
const name = dirs
|
43
|
+
// with something like "ariadne-controllername"
|
44
|
+
const name = dirs[dirs.length - 1].replace('_controller.ts', '').replaceAll('_', '-').toLocaleLowerCase()
|
45
45
|
|
46
46
|
application.register(
|
47
47
|
// @tag stimulus-id
|
data/app/frontend/controllers/{autosubmittable_controller.ts → form_autosubmit_controller.ts}
RENAMED
@@ -2,8 +2,7 @@ import {Controller} from '@hotwired/stimulus'
|
|
2
2
|
|
3
3
|
import {useDebounce} from 'stimulus-use'
|
4
4
|
|
5
|
-
|
6
|
-
export default class AutoSubmittableController extends Controller<HTMLFormElement> {
|
5
|
+
export default class FormAutosubmitController extends Controller<HTMLFormElement> {
|
7
6
|
static debounces = ['save']
|
8
7
|
static targets = ['form']
|
9
8
|
declare readonly formTarget: HTMLFormElement
|