ariadne_view_components 0.0.80.3 → 0.0.82

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/app/assets/javascripts/ariadne_view_components.js +14 -14
  4. data/app/assets/javascripts/ariadne_view_components.js.br +0 -0
  5. data/app/assets/javascripts/ariadne_view_components.js.gz +0 -0
  6. data/app/assets/javascripts/ariadne_view_components.js.map +1 -1
  7. data/app/assets/stylesheets/ariadne_view_components.css +1 -1
  8. data/app/assets/stylesheets/ariadne_view_components.css.br +0 -0
  9. data/app/assets/stylesheets/ariadne_view_components.css.gz +0 -0
  10. data/app/components/ariadne/base_component.rb +5 -1
  11. data/app/components/ariadne/form/checkbox/component.html.erb +21 -5
  12. data/app/components/ariadne/form/checkbox/component.rb +36 -0
  13. data/app/components/ariadne/form/group/component.html.erb +0 -2
  14. data/app/components/ariadne/form/group/component.rb +4 -1
  15. data/app/components/ariadne/form/text_field/component.rb +26 -23
  16. data/app/components/ariadne/ui/badge/component.rb +12 -17
  17. data/app/components/ariadne/ui/button/component.rb +1 -0
  18. data/app/components/ariadne/ui/combobox/component.html.erb +5 -17
  19. data/app/components/ariadne/ui/combobox/component.rb +8 -28
  20. data/app/components/ariadne/ui/combobox/component.ts +24 -39
  21. data/app/components/ariadne/ui/dialog/component.rb +18 -2
  22. data/app/components/ariadne/ui/flash/component.html.erb +11 -11
  23. data/app/components/ariadne/ui/flash/component.rb +30 -12
  24. data/app/components/ariadne/ui/link/component.rb +21 -5
  25. data/app/components/ariadne/ui/list/component.html.erb +28 -4
  26. data/app/components/ariadne/ui/list/component.rb +119 -1
  27. data/app/components/ariadne/ui/list/component.ts +57 -0
  28. data/app/components/ariadne/ui/popover/component.html.erb +4 -4
  29. data/app/components/ariadne/ui/popover/component.rb +3 -1
  30. data/app/components/ariadne/ui/popover/component.ts +1 -1
  31. data/app/components/ariadne/ui/typography/component.rb +19 -0
  32. data/app/frontend/ariadne/stimulus_app.ts +2 -2
  33. data/app/frontend/controllers/{autosubmittable_controller.ts → form_autosubmit_controller.ts} +1 -2
  34. data/app/lib/ariadne/view_component/style_variants.rb +50 -0
  35. data/lib/ariadne/forms/dsl/badge.rb +2 -2
  36. data/lib/ariadne/forms/dsl/button_input.rb +2 -1
  37. data/lib/ariadne/forms/dsl/clipboard_copy_button.rb +34 -0
  38. data/lib/ariadne/forms/dsl/input_methods.rb +4 -0
  39. data/lib/ariadne/view_components/version.rb +1 -1
  40. metadata +5 -9
  41. data/app/components/ariadne/ui/combobox/item/component.html.erb +0 -9
  42. data/app/components/ariadne/ui/combobox/item/component.rb +0 -61
  43. data/app/components/ariadne/ui/combobox/option/component.html.erb +0 -11
  44. data/app/components/ariadne/ui/combobox/option/component.rb +0 -44
  45. data/app/components/ariadne/ui/list/item/component.html.erb +0 -16
  46. 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
- anchor: null,
8
- options: null,
9
- popover: null,
10
- searchInput: HTMLInputElement,
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.setupClickHandlers()
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.anchorTarget, this.popoverTarget, {
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
- const inputHeight = searchInput ? searchInput.getBoundingClientRect().height : 0
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.anchorTarget, this.popoverTarget, updatePopoverPosition)
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
- <div class="ariadne-flex-shrink-0 <%= style(:text, type:) %>">
4
+ <div class="ariadne-flex-shrink-0 <%= style(:text, type:) %>">
5
5
  <%= icon %>
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 "><%= title %></p>
9
- <p class="ariadne-mt-1 ariadne-text-sm "><%= message %></p>
10
- </div>
11
- <div class="ariadne-ml-4 ariadne-flex ariadne-flex-shrink-0 ">
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
- <%= 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) %>
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
- </div>
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
- html_attrs[:data] = {
15
- controller: "flash",
16
- transition_enter: "ariadne-transform ariadne-ease-out ariadne-duration-300 ariadne-transition-all",
17
- transition_enter_start: "ariadne-translate-y-2 ariadne-opacity-0 sm:ariadne-translate-y-0 sm:ariadne-translate-x-2",
18
- transition_enter_end: "ariadne-translate-y-0 ariadne-opacity-100 sm:ariadne-translate-x-0",
19
- transition_leave: "ariadne-transition-all ariadne-ease-in ariadne-duration-100",
20
- transition_leave_start: "ariadne-opacity-100",
21
- transition_leave_end: "ariadne-opacity-0",
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
- "hover:ariadne-text-indigo-600",
38
- "dark:hover:ariadne-text-indigo-400",
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-600",
42
- "dark:focus:ariadne-text-indigo-400",
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
- nude { "" }
64
+
49
65
  thick { "ariadne-font-semibold" }
50
66
  end
51
67
  size do
@@ -1,6 +1,30 @@
1
-
2
- <ol class="ariadne-divide-y ariadne-divide-zinc-100 dark:ariadne-divide-zinc-800">
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
- <li><%= item %></li>
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
- </ol>
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
- renders_many :items, Ariadne::UI::List::Item::Component
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
- <%= content %>
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" => ["toggle", html_attrs.fetch(:data, {}).fetch(:target, nil)].compact.join(" "),
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.target.style, {
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-component-name"
44
- const name = dirs.slice(2, dirs.length).join('-').replace('.ts', '').replaceAll('_', '-').toLocaleLowerCase()
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
@@ -2,8 +2,7 @@ import {Controller} from '@hotwired/stimulus'
2
2
 
3
3
  import {useDebounce} from 'stimulus-use'
4
4
 
5
- // can't use controllerFactory because it seems to conflict with `useDebounce`
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