hotwire_combobox 0.2.0 → 0.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ddf9dd6a046c3871c1b3935a8a2e9e899a88787ba6d39e673ec8eee792c920dc
4
- data.tar.gz: f6d207f71a8ce4779df0cc12cd4264106b1fb086319bc8ad4c303a22604f2f1c
3
+ metadata.gz: 9649cc031cc63f665e78c4f72857f72698d42af893d8204cab739a5817be27b8
4
+ data.tar.gz: f9e791cc61927caebd9db3c32cf3e71382f6d77e4f54c8275348b02600fce8d4
5
5
  SHA512:
6
- metadata.gz: 5cb541bd15115ee71ed82dea3d2c922abcd9c8279f835b7d6074fd825cbd08e6ac40d1b181b398ee6d00a1e4c7d7fc3f18892134cc362aa98640519ee27b9030
7
- data.tar.gz: a6adeb3593a0f25d9a726be101c52c00488d367592d134c089d520cc6a087eff67f00b5f965fcc8b1c09e6c1f6f96e955815d234cdc19162a1dc657a83271183
6
+ metadata.gz: 5f6c132e19554295758e13763663a6e0d3b0e7a0a413088a25aed723370dd5967133af3e2660e9ef4ecb16d661f39232bb36ac9c08c37531b36677f2a8c0d961
7
+ data.tar.gz: 6461c5650345338c17dd33dd378575d5376e2b31ed9466aa4b527096ae831db8feac8b73f357dc8da7908dd7e41aeed1a6750bd9bc1cd570c6e5634562aca0f9
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # Easy and Accessible Autocomplete for Ruby on Rails
6
6
 
7
- [![CI Tests](https://github.com/josefarias/hotwire_combobox/actions/workflows/ci_tests.yml/badge.svg)](https://github.com/josefarias/hotwire_combobox/actions/workflows/ci_tests.yml) [![Gem Version](https://badge.fury.io/rb/hotwire_combobox.svg)](https://badge.fury.io/rb/hotwire_combobox)
7
+ [![CI](https://github.com/josefarias/hotwire_combobox/actions/workflows/ci.yml/badge.svg)](https://github.com/josefarias/hotwire_combobox/actions/workflows/ci.yml) [![Gem Version](https://badge.fury.io/rb/hotwire_combobox.svg)](https://badge.fury.io/rb/hotwire_combobox)
8
8
 
9
9
 
10
10
  > [!IMPORTANT]
@@ -65,6 +65,10 @@ export default class HwComboboxController extends Concerns(...concerns) {
65
65
  }
66
66
 
67
67
  connect() {
68
+ this.idempotentConnect()
69
+ }
70
+
71
+ idempotentConnect() {
68
72
  this._connectSelection()
69
73
  this._connectListAutocomplete()
70
74
  this._connectDialog()
@@ -1,5 +1,5 @@
1
1
  /*!
2
- HotwireCombobox 0.2.0
2
+ HotwireCombobox 0.2.1
3
3
  */
4
4
  import { Controller } from '@hotwired/stimulus';
5
5
 
@@ -1706,6 +1706,10 @@ class HwComboboxController extends Concerns(...concerns) {
1706
1706
  }
1707
1707
 
1708
1708
  connect() {
1709
+ this.idempotentConnect();
1710
+ }
1711
+
1712
+ idempotentConnect() {
1709
1713
  this._connectSelection();
1710
1714
  this._connectListAutocomplete();
1711
1715
  this._connectDialog();
@@ -1,5 +1,5 @@
1
1
  /*!
2
- HotwireCombobox 0.2.0
2
+ HotwireCombobox 0.2.1
3
3
  */
4
4
  (function (global, factory) {
5
5
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@hotwired/stimulus')) :
@@ -1710,6 +1710,10 @@ HotwireCombobox 0.2.0
1710
1710
  }
1711
1711
 
1712
1712
  connect() {
1713
+ this.idempotentConnect();
1714
+ }
1715
+
1716
+ idempotentConnect() {
1713
1717
  this._connectSelection();
1714
1718
  this._connectListAutocomplete();
1715
1719
  this._connectDialog();
@@ -2,6 +2,7 @@
2
2
  --hw-active-bg-color: #F3F4F6;
3
3
  --hw-border-color: #D1D5DB;
4
4
  --hw-group-color: #57595C;
5
+ --hw-group-bg-color: #FFFFFF;
5
6
  --hw-invalid-color: #EF4444;
6
7
  --hw-dialog-label-color: #1D1D1D;
7
8
  --hw-focus-color: #2563EB;
@@ -78,7 +79,7 @@
78
79
  }
79
80
 
80
81
  .hw-combobox__input {
81
- border: 0;
82
+ border: none;
82
83
  font-size: inherit;
83
84
  line-height: var(--hw-line-height);
84
85
  min-width: 0;
@@ -87,7 +88,10 @@
87
88
  width: 100%;
88
89
  }
89
90
 
90
- .hw-combobox__input:focus-visible {
91
+ .hw-combobox__input:focus,
92
+ .hw-combobox__input:focus-visible,
93
+ .hw-combobox__input:focus-within {
94
+ box-shadow: none;
91
95
  outline: none;
92
96
  }
93
97
 
@@ -145,6 +149,7 @@
145
149
  }
146
150
 
147
151
  .hw-combobox__group__label {
152
+ background-color: var(--hw-group-bg-color);
148
153
  color: var(--hw-group-color);
149
154
  padding: var(--hw-padding--slim);
150
155
  }
@@ -238,23 +238,29 @@ class HotwireCombobox::Component
238
238
  end
239
239
 
240
240
  def prefilled_display
241
- return if multiselect?
241
+ return if multiselect? || !hidden_field_value
242
242
 
243
243
  if async_src && associated_object
244
244
  associated_object.to_combobox_display
245
- elsif hidden_field_value
246
- options.find { |option| option.value == hidden_field_value }&.autocompletable_as
245
+ elsif async_src && form_object&.respond_to?(name)
246
+ form_object.public_send name
247
+ else
248
+ options.find_by_value(hidden_field_value)&.autocompletable_as
247
249
  end
248
250
  end
249
251
 
250
252
  def associated_object
251
253
  @associated_object ||= if association_exists?
252
- form.object.public_send association_name
254
+ form_object&.public_send association_name
253
255
  end
254
256
  end
255
257
 
256
258
  def association_exists?
257
- form&.object&.class&.reflect_on_association(association_name).present?
259
+ form_object&.class&.reflect_on_association(association_name).present?
260
+ end
261
+
262
+ def form_object
263
+ form&.object
258
264
  end
259
265
 
260
266
  def async_src
@@ -302,10 +308,10 @@ class HotwireCombobox::Component
302
308
  def hidden_field_value
303
309
  return value if value
304
310
 
305
- if form&.object&.defined_enums&.try :[], name
306
- form.object.public_send "#{name}_before_type_cast"
311
+ if form_object&.defined_enums&.try :[], name
312
+ form_object.public_send "#{name}_before_type_cast"
307
313
  else
308
- form&.object&.try(name).then do |value|
314
+ form_object&.try(name).then do |value|
309
315
  value.respond_to?(:map) ? value.join(",") : value
310
316
  end
311
317
  end
@@ -329,7 +335,8 @@ class HotwireCombobox::Component
329
335
  click@window->hw-combobox#closeOnClickOutside
330
336
  focusin@window->hw-combobox#closeOnFocusOutside
331
337
  turbo:before-stream-render@document->hw-combobox#rerouteListboxStreamToDialog
332
- turbo:before-cache@document->hw-combobox#hideChipsForCache".squish,
338
+ turbo:before-cache@document->hw-combobox#hideChipsForCache
339
+ turbo:morph-element->hw-combobox#idempotentConnect".squish,
333
340
  hw_combobox_target: "combobox",
334
341
  async_id: canonical_id
335
342
  end
@@ -1,6 +1,8 @@
1
1
  require "securerandom"
2
2
 
3
3
  class HotwireCombobox::Listbox::Group
4
+ attr_reader :options
5
+
4
6
  def initialize(name, options:)
5
7
  @name = name
6
8
  @options = options
@@ -17,7 +19,7 @@ class HotwireCombobox::Listbox::Group
17
19
  end
18
20
 
19
21
  private
20
- attr_reader :name, :options
22
+ attr_reader :name
21
23
 
22
24
  def id
23
25
  @id ||= SecureRandom.uuid
@@ -0,0 +1,14 @@
1
+ class HotwireCombobox::Listbox::Item::Collection < Array
2
+ def find_by_value(value)
3
+ if grouped?
4
+ flat_map { |item| item.options }.find { |option| option.value == value }
5
+ else
6
+ find { |option| option.value == value }
7
+ end
8
+ end
9
+
10
+ private
11
+ def grouped?
12
+ first.is_a? HotwireCombobox::Listbox::Group
13
+ end
14
+ end
@@ -1,7 +1,7 @@
1
1
  class HotwireCombobox::Listbox::Item
2
2
  class << self
3
3
  def collection_for(view, options, render_in:, include_blank:, **custom_methods)
4
- new(view, options, render_in: render_in, include_blank: include_blank, **custom_methods).items
4
+ new(view, options, render_in: render_in, include_blank: include_blank, **custom_methods).collection
5
5
  end
6
6
  end
7
7
 
@@ -13,10 +13,10 @@ class HotwireCombobox::Listbox::Item
13
13
  @custom_methods = custom_methods
14
14
  end
15
15
 
16
- def items
16
+ def collection
17
17
  items = groups_or_options
18
18
  items.unshift(blank_option) if include_blank.present?
19
- items
19
+ Collection.new items
20
20
  end
21
21
 
22
22
  private
@@ -31,7 +31,7 @@ class HotwireCombobox::Listbox::Item
31
31
  end
32
32
 
33
33
  def grouped?
34
- key, value = options.to_a.first
34
+ _key, value = options.to_a.first
35
35
  value.is_a? Array
36
36
  end
37
37
 
@@ -43,8 +43,12 @@ class HotwireCombobox::Listbox::Item
43
43
  end
44
44
 
45
45
  def create_listbox_options(options)
46
- options.map do |option|
47
- HotwireCombobox::Listbox::Option.new **option_attrs(option)
46
+ if options.first.is_a? HotwireCombobox::Listbox::Option
47
+ options
48
+ else
49
+ options.map do |option|
50
+ HotwireCombobox::Listbox::Option.new **option_attrs(option)
51
+ end
48
52
  end
49
53
  end
50
54
 
@@ -93,12 +97,15 @@ class HotwireCombobox::Listbox::Item
93
97
  end
94
98
 
95
99
  def extract_blank_display_and_content
96
- if include_blank.is_a? Hash
100
+ case include_blank
101
+ when Hash
97
102
  text = include_blank.delete(:text)
98
103
 
99
104
  [ text, render_content(render_opts: include_blank, object: text, attrs: { display: text, value: "" }) ]
100
- else
105
+ when String
101
106
  [ include_blank, include_blank ]
107
+ else
108
+ [ "", "&nbsp;".html_safe ]
102
109
  end
103
110
  end
104
111
  end
@@ -17,10 +17,6 @@ class HotwireCombobox::Listbox::Option
17
17
  option.try(:autocompletable_as) || option.try(:display)
18
18
  end
19
19
 
20
- def content
21
- option.try(:content) || option.try(:display)
22
- end
23
-
24
20
  private
25
21
  Data = Struct.new :id, :value, :display, :content, :blank, :filterable_as, :autocompletable_as, keyword_init: true
26
22
 
@@ -57,6 +53,10 @@ class HotwireCombobox::Listbox::Option
57
53
  option.try(:filterable_as) || option.try(:display)
58
54
  end
59
55
 
56
+ def content
57
+ option.try(:content) || option.try(:display)
58
+ end
59
+
60
60
  def blank?
61
61
  option.try(:blank).present?
62
62
  end
@@ -26,16 +26,12 @@ module HotwireCombobox
26
26
  include_blank: nil,
27
27
  display: :to_combobox_display,
28
28
  **custom_methods)
29
- if options.first.is_a? HotwireCombobox::Listbox::Option
30
- options
31
- else
32
- HotwireCombobox::Listbox::Item.collection_for \
33
- self,
34
- options,
35
- render_in: render_in,
36
- include_blank: include_blank,
37
- **custom_methods.merge(display: display)
38
- end
29
+ HotwireCombobox::Listbox::Item.collection_for \
30
+ self,
31
+ options,
32
+ render_in: render_in,
33
+ include_blank: include_blank,
34
+ **custom_methods.merge(display: display)
39
35
  end
40
36
 
41
37
  def hw_paginated_combobox_options(
@@ -184,7 +180,7 @@ module HotwireCombobox
184
180
  private
185
181
  def hw_extract_options_and_src(options_or_src, render_in, include_blank)
186
182
  if options_or_src.is_a? String
187
- [ [], options_or_src ]
183
+ [ hw_combobox_options([]), options_or_src ]
188
184
  else
189
185
  [ hw_combobox_options(options_or_src, render_in: render_in, include_blank: include_blank), nil ]
190
186
  end
@@ -1,3 +1,3 @@
1
1
  module HotwireCombobox
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hotwire_combobox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jose Farias
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-22 00:00:00.000000000 Z
11
+ date: 2024-03-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -91,6 +91,7 @@ files:
91
91
  - app/presenters/hotwire_combobox/component/customizable.rb
92
92
  - app/presenters/hotwire_combobox/listbox/group.rb
93
93
  - app/presenters/hotwire_combobox/listbox/item.rb
94
+ - app/presenters/hotwire_combobox/listbox/item/collection.rb
94
95
  - app/presenters/hotwire_combobox/listbox/option.rb
95
96
  - app/views/hotwire_combobox/_component.html.erb
96
97
  - app/views/hotwire_combobox/_next_page.turbo_stream.erb
@@ -129,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
129
130
  - !ruby/object:Gem::Version
130
131
  version: '0'
131
132
  requirements: []
132
- rubygems_version: 3.5.6
133
+ rubygems_version: 3.4.18
133
134
  signing_key:
134
135
  specification_version: 4
135
136
  summary: Accessible Autocomplete for Rails apps