hotwire_combobox 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 06d497472d7966424ceea6dc655bf8baf2bfa7b2232ab587bb1ca6221f1b8e13
4
- data.tar.gz: 994345e54975287e4958e917d8ff687851e6628604249c5ec59e2bcf9a858fb2
3
+ metadata.gz: 01a08bf7fdf486660daebfd29960a62c8435ad87939a8963d805967872ffca4d
4
+ data.tar.gz: 2ca73e1f2693d9adf838463187bd2c79867b8086d59beea0bb699c12a49e8507
5
5
  SHA512:
6
- metadata.gz: b3bd3a8d9266f43a542641f762ae059d2f8cc2a5c3d98f14b8a853bc5173fd5b382482fa89c0ff103df7e3e24fbf06a6aad5fccffe4d01bd3194959114610742
7
- data.tar.gz: aa29ec37fa9fd51d640622686a91f6e2bf31c6c9df6a1618d88d540dcea3c1f6e5033379bf0397726904a34a19927bb1b5e9b016d797e7e861d993229e79d171
6
+ metadata.gz: d505fbfb95060cb730a5533dd4d850f4691391a94f4849fd12017f1ebca12df55a12871d29f784e55dccbe2a8512c007c7516f960225e1a13f6ab74d5d8a3431
7
+ data.tar.gz: 6792bae8acf5f9051f2a5605f95e86d7e3b755d323e47e9dff65dc0a02eb27771fa145d2129b246518711e4b050cc2e3cba8b03e83b581ea519c31c30a2ad5d6
data/README.md CHANGED
@@ -1,8 +1,9 @@
1
- # Hotwire Combobox
2
- Short description and motivation.
1
+ # HotwireCombobox
3
2
 
4
- ## Usage
5
- How to use my plugin.
3
+ A combobox implementation for Ruby on Rails apps running on Hotwire.
4
+
5
+ > [!WARNING]
6
+ > This gem is pre-release software. It's not ready for production use yet and the API is subject to change.
6
7
 
7
8
  ## Installation
8
9
  Add this line to your application's Gemfile:
@@ -16,11 +17,97 @@ And then execute:
16
17
  $ bundle
17
18
  ```
18
19
 
19
- Or install it yourself as:
20
- ```bash
21
- $ gem install hotwire_combobox
20
+ ## Output
21
+
22
+ This is the stripped-down output of a combobox generated with HotwireCombobox. Understanding it will be helpful in getting the most out of this library.
23
+
24
+ ```html
25
+ <fieldset class="hw-combobox">
26
+ <input type="hidden" name="provided_name">
27
+
28
+ <input type="text" role="combobox">
29
+
30
+ <ul role="listbox">
31
+ <li role="option">Provided Option 1 Content</li>
32
+ <li role="option">Provided Option 2 Content</li>
33
+ <!-- ... -->
34
+ </ul>
35
+ </fieldset>
36
+ ```
37
+
38
+ The `<ul role="listbox">` element is what gets shown when the combobox is open.
39
+
40
+ The library uses stimulus to add interactivity to the combobox and sync the input element's value with the hidden input element.
41
+
42
+ The hidden input's value is what ultimately gets sent to the server when submitting a form containing the combobox.
43
+
44
+ ## Usage
45
+
46
+ ### Options
47
+
48
+ Options are what you see when you open the combobox.
49
+
50
+ The `options` argument takes an array of any objects which respond to:
51
+
52
+ | Attribute | Description | Required? |
53
+ |----------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------|-------------------|
54
+ | `id` | Used as the option element's `id` attribute. Only required if `value` is not provided. | Required* |
55
+ | `value` | Used to populate the input element's `value` attribute. Falls back to calling `id` on the object if not provided. | Optional |
56
+ | `content` <br> **Supports HTML** | Used as the option element's content. Falls back to calling `display` on the object if not provided. | Optional |
57
+ | `filterable_as` | Used to filter down the options when the user types into the input element. Falls back to calling `display` on the object if not provided. | Optional |
58
+ | `autocompletable_as` | Used to autocomplete the input element when the user types into it. Falls back to calling `display` on the object if not provided. | Optional |
59
+ | `display` | Used as a short-hand for other attributes. See the rest of the list for details. | Optional |
60
+
61
+
62
+ > [!NOTE]
63
+ > The `id` attribute is required only if `value` is not provided.
64
+
65
+
66
+ The gem provides a `HotwireCombobox::Option` class which you can use to create options:
67
+
68
+ ```ruby
69
+ @states = [
70
+ HotwireCombobox::Option.new(value: "AL", display: "Alabama"),
71
+ # ...
72
+ ]
73
+ ```
74
+
75
+ If you feel `HotwireCombobox::Option` is too verbose, you can also use the `hwbox_options` helper. It will destructure the hashes you pass to it and create `HotwireCombobox::Option` instances for you:
76
+
77
+ ```ruby
78
+ @states = hwbox_options [
79
+ { value: "AL", display: "Alabama" },
80
+ # ...
81
+ ]
22
82
  ```
23
83
 
84
+ ### Styling
85
+
86
+ The combobox is completely unstyled by default. You can use the following CSS selectors to style the combobox:
87
+
88
+ * `.hw-combobox` targets the `<fieldset>` element used to wrap the whole component.
89
+ * `.hw-combobox [role="combobox"]` targets the input element.
90
+ * `.hw-combobox [role="listbox"]` targets the listbox which encloses all option elements.
91
+ * `.hw-combobox [role="option"]` targets each option element inside the listbox.
92
+
93
+ Additionally, you can pass the following [Stimulus class values](https://stimulus.hotwired.dev/reference/css-classes) to `hw_combobox_tag`:
94
+
95
+ * `data-hw-combobox-selected-class`: The class to apply to the selected option while shown inside an open listbox.
96
+ * `data-hw-combobox-invalid-class`: The class to apply to the input element when the current value is invalid.
97
+
98
+ ### Validity
99
+
100
+ The hidden input can't have a value that's not in the list of options.
101
+
102
+ If a nonexistent value is typed into the combobox, the value of the hidden input will be set empty.
103
+
104
+ The only way a value can be marked as invalid is if the field is required and empty after having interacted with the combobox.
105
+
106
+ The library will mark the element as invalid but this won't be noticeable in the UI unless you specify styles for the invalid state. See the [Styling](#styling) section for details.
107
+
108
+ > [!CAUTION]
109
+ > Bad actors can still submit invalid values to the server. You should always validate the input on the server side.
110
+
24
111
  ## Contributing
25
112
 
26
113
  ### Setup
@@ -1,5 +1,13 @@
1
1
  module HotwireCombobox
2
2
  module Helper
3
+ def hwbox_option(...)
4
+ HotwireCombobox::Option.new(...)
5
+ end
6
+
7
+ def hwbox_options(options)
8
+ options.map { |option| hwbox_option(**option) }
9
+ end
10
+
3
11
  def hw_combobox_tag(name, value = nil, form: nil, options: [], data: {}, input: {}, **attrs)
4
12
  value_field_attrs = {}.tap do |h|
5
13
  h[:id] = default_hw_combobox_value_field_id attrs, form, name
@@ -20,10 +28,26 @@ module HotwireCombobox
20
28
  parent_data: default_hw_combobox_parent_data(attrs, data)
21
29
  end
22
30
 
23
- def value_for_hw_listbox_option(option)
31
+ def hw_listbox_option_id(option)
32
+ option.try(:id)
33
+ end
34
+
35
+ def hw_listbox_option_value(option)
24
36
  option.try(:value) || option.id
25
37
  end
26
38
 
39
+ def hw_listbox_option_content(option)
40
+ option.try(:content) || option.try(:display)
41
+ end
42
+
43
+ def hw_listbox_option_filterable_as(option)
44
+ option.try(:filterable_as) || option.try(:display)
45
+ end
46
+
47
+ def hw_listbox_option_autocompletable_as(option)
48
+ option.try(:autocompletable_as) || option.try(:display)
49
+ end
50
+
27
51
  private
28
52
  def default_hw_combobox_value_field_id(attrs, form, name)
29
53
  attrs.delete(:id) || form&.field_id(name)
@@ -7,13 +7,15 @@
7
7
  <%= tag.ul id: listbox_id, hidden: "", role: :listbox,
8
8
  data: { "hw-combobox-target": "listbox" } do |ul| %>
9
9
  <% options.each do |option| %>
10
- <%= tag.li option.content, id: option.try(:id),
11
- role: :option, style: "cursor: pointer;",
10
+ <%= tag.li hw_listbox_option_content(option),
11
+ id: hw_listbox_option_id(option),
12
+ role: :option,
13
+ style: "cursor: pointer;",
12
14
  data: {
13
15
  "action": "click->hw-combobox#selectOption",
14
- "filterable-as": option.try(:filterable_as),
15
- "autocompletable-as": option.try(:autocompletable_as),
16
- "value": value_for_hw_listbox_option(option) } %>
16
+ "filterable-as": hw_listbox_option_filterable_as(option),
17
+ "autocompletable-as": hw_listbox_option_autocompletable_as(option),
18
+ "value": hw_listbox_option_value(option) } %>
17
19
  <% end %>
18
20
  <% end %>
19
21
  <% end %>
@@ -1,3 +1,3 @@
1
1
  module HotwireCombobox
2
- VERSION = "0.1.6"
2
+ VERSION = "0.1.7"
3
3
  end
@@ -2,5 +2,5 @@ require "hotwire_combobox/version"
2
2
  require "hotwire_combobox/engine"
3
3
 
4
4
  module HotwireCombobox
5
- Option = Struct.new(:id, :value, :content, :filterable_as, :autocompletable_as)
5
+ Option = Struct.new(:id, :value, :display, :content, :filterable_as, :autocompletable_as)
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hotwire_combobox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jose Farias