hotwire_combobox 0.1.31 → 0.1.33
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/README.md +2 -0
- data/app/assets/javascripts/controllers/hw_combobox_controller.js +3 -2
- data/app/assets/javascripts/{helpers.js → hw_combobox/helpers.js} +6 -0
- data/app/assets/javascripts/{models → hw_combobox/models}/combobox/actors.js +1 -1
- data/app/assets/javascripts/{models → hw_combobox/models}/combobox/async_loading.js +1 -1
- data/app/assets/javascripts/{models → hw_combobox/models}/combobox/autocomplete.js +17 -2
- data/app/assets/javascripts/{models → hw_combobox/models}/combobox/dialog.js +1 -1
- data/app/assets/javascripts/{models → hw_combobox/models}/combobox/filtering.js +13 -11
- data/app/assets/javascripts/{models → hw_combobox/models}/combobox/navigation.js +2 -2
- data/app/assets/javascripts/hw_combobox/models/combobox/new_options.js +37 -0
- data/app/assets/javascripts/{models → hw_combobox/models}/combobox/options.js +2 -10
- data/app/assets/javascripts/{models → hw_combobox/models}/combobox/selection.js +16 -4
- data/app/assets/javascripts/{models → hw_combobox/models}/combobox/toggle.js +3 -5
- data/app/assets/javascripts/{models → hw_combobox/models}/combobox/validity.js +1 -1
- data/app/assets/javascripts/hw_combobox/models/combobox.js +15 -0
- data/app/assets/stylesheets/hotwire_combobox.css +0 -1
- data/app/presenters/hotwire_combobox/component.rb +11 -5
- data/lib/hotwire_combobox/engine.rb +1 -1
- data/lib/hotwire_combobox/helper.rb +41 -26
- data/lib/hotwire_combobox/version.rb +1 -1
- metadata +20 -22
- data/app/assets/javascripts/controllers/application.js +0 -9
- data/app/assets/javascripts/controllers/index.js +0 -3
- data/app/assets/javascripts/hotwire_combobox_application.js +0 -1
- data/app/assets/javascripts/models/combobox.js +0 -14
- /data/app/assets/javascripts/{models → hw_combobox/models}/combobox/base.js +0 -0
- /data/app/assets/javascripts/{vendor → hw_combobox/vendor}/bodyScrollLock.js +0 -0
- /data/app/assets/javascripts/{vendor → hw_combobox/vendor}/requestjs.js +0 -0
- /data/config/{importmap.rb → hw_importmap.rb} +0 -0
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 415f50ba9630121312ea65c8f04435ff57ba386ffb9851dc9e09da8a6dc68352
         | 
| 4 | 
            +
              data.tar.gz: de3d2d2bfb9d9f9e21292acf49152484ad05317b16daade967ea695afbf3bc87
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: aab8d6575ec896e26035b5040afa0765b3dacd92d101589b20f305840a5831174cad852325bc64971e83f182260454d2d836be665f19a33cf845d972d90b8134
         | 
| 7 | 
            +
              data.tar.gz: 5f4393d0d3dbf29c9bf194210cf7d845c35062a7fd4d952e6acafae2c407ce158d63735f703419311c15ab3996002fa573617cbff26b98406d7e98bdf0e85e9f
         | 
    
        data/README.md
    CHANGED
    
    
| @@ -1,5 +1,5 @@ | |
| 1 | 
            -
            import Combobox from "models/combobox"
         | 
| 2 | 
            -
            import { Concerns } from "helpers"
         | 
| 1 | 
            +
            import Combobox from "hw_combobox/models/combobox"
         | 
| 2 | 
            +
            import { Concerns } from "hw_combobox/helpers"
         | 
| 3 3 | 
             
            import { Controller } from "@hotwired/stimulus"
         | 
| 4 4 |  | 
| 5 5 | 
             
            const concerns = [
         | 
| @@ -10,6 +10,7 @@ const concerns = [ | |
| 10 10 | 
             
              Combobox.Dialog,
         | 
| 11 11 | 
             
              Combobox.Filtering,
         | 
| 12 12 | 
             
              Combobox.Navigation,
         | 
| 13 | 
            +
              Combobox.NewOptions,
         | 
| 13 14 | 
             
              Combobox.Options,
         | 
| 14 15 | 
             
              Combobox.Selection,
         | 
| 15 16 | 
             
              Combobox.Toggle,
         | 
| @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            export const nullEvent = new Event("NULL")
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            export function Concerns(Base, ...mixins) {
         | 
| 2 4 | 
             
              return mixins.reduce((accumulator, current) => current(accumulator), Base)
         | 
| 3 5 | 
             
            }
         | 
| @@ -50,3 +52,7 @@ export function debounce(fn, delay = 150) { | |
| 50 52 | 
             
                timeoutId = setTimeout(callback, delay)
         | 
| 51 53 | 
             
              }
         | 
| 52 54 | 
             
            }
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            export function isDeleteEvent(event) {
         | 
| 57 | 
            +
              return event.inputType === "deleteContentBackward" || event.inputType === "deleteWordBackward"
         | 
| 58 | 
            +
            }
         | 
| @@ -1,5 +1,5 @@ | |
| 1 | 
            -
            import Combobox from "models/combobox/base"
         | 
| 2 | 
            -
            import { startsWith } from "helpers"
         | 
| 1 | 
            +
            import Combobox from "hw_combobox/models/combobox/base"
         | 
| 2 | 
            +
            import { startsWith } from "hw_combobox/helpers"
         | 
| 3 3 |  | 
| 4 4 | 
             
            Combobox.Autocomplete = Base => class extends Base {
         | 
| 5 5 | 
             
              _connectListAutocomplete() {
         | 
| @@ -29,6 +29,17 @@ Combobox.Autocomplete = Base => class extends Base { | |
| 29 29 | 
             
                this.listboxTarget.style.display = "none"
         | 
| 30 30 | 
             
              }
         | 
| 31 31 |  | 
| 32 | 
            +
              get _isExactAutocompleteMatch() {
         | 
| 33 | 
            +
                return this._immediatelyAutocompletableValue === this._actingCombobox.value
         | 
| 34 | 
            +
              }
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              // All `_isExactAutocompleteMatch` matches are `_isPartialAutocompleteMatch` matches
         | 
| 37 | 
            +
              // but not all `_isPartialAutocompleteMatch` matches are `_isExactAutocompleteMatch` matches.
         | 
| 38 | 
            +
              get _isPartialAutocompleteMatch() {
         | 
| 39 | 
            +
                return !!this._immediatelyAutocompletableValue &&
         | 
| 40 | 
            +
                  startsWith(this._immediatelyAutocompletableValue, this._actingCombobox.value)
         | 
| 41 | 
            +
              }
         | 
| 42 | 
            +
             | 
| 32 43 | 
             
              get _autocompletesList() {
         | 
| 33 44 | 
             
                return this.autocompleteValue === "both" || this.autocompleteValue === "list"
         | 
| 34 45 | 
             
              }
         | 
| @@ -36,4 +47,8 @@ Combobox.Autocomplete = Base => class extends Base { | |
| 36 47 | 
             
              get _autocompletesInline() {
         | 
| 37 48 | 
             
                return this.autocompleteValue === "both" || this.autocompleteValue === "inline"
         | 
| 38 49 | 
             
              }
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              get _immediatelyAutocompletableValue() {
         | 
| 52 | 
            +
                return this._visibleOptionElements[0]?.getAttribute(this.autocompletableAttributeValue)
         | 
| 53 | 
            +
              }
         | 
| 39 54 | 
             
            }
         | 
| @@ -1,7 +1,7 @@ | |
| 1 1 |  | 
| 2 | 
            -
            import Combobox from "models/combobox/base"
         | 
| 3 | 
            -
            import { applyFilter, nextFrame, debounce } from "helpers"
         | 
| 4 | 
            -
            import { get } from "vendor/requestjs"
         | 
| 2 | 
            +
            import Combobox from "hw_combobox/models/combobox/base"
         | 
| 3 | 
            +
            import { applyFilter, nextFrame, debounce, isDeleteEvent } from "hw_combobox/helpers"
         | 
| 4 | 
            +
            import { get } from "hw_combobox/vendor/requestjs"
         | 
| 5 5 |  | 
| 6 6 | 
             
            Combobox.Filtering = Base => class extends Base {
         | 
| 7 7 | 
             
              filter(event) {
         | 
| @@ -25,7 +25,7 @@ Combobox.Filtering = Base => class extends Base { | |
| 25 25 |  | 
| 26 26 | 
             
                await get(this.asyncSrcValue, { responseKind: "turbo-stream", query: { q } })
         | 
| 27 27 |  | 
| 28 | 
            -
                this._afterTurboStreamRender(() => this._commitFilter( | 
| 28 | 
            +
                this._afterTurboStreamRender(() => this._commitFilter(event))
         | 
| 29 29 | 
             
              }
         | 
| 30 30 |  | 
| 31 31 | 
             
              _filterSync(event) {
         | 
| @@ -35,15 +35,13 @@ Combobox.Filtering = Base => class extends Base { | |
| 35 35 |  | 
| 36 36 | 
             
                this._allOptionElements.forEach(applyFilter(query, { matching: this.filterableAttributeValue }))
         | 
| 37 37 |  | 
| 38 | 
            -
                this._commitFilter( | 
| 38 | 
            +
                this._commitFilter(event)
         | 
| 39 39 | 
             
              }
         | 
| 40 40 |  | 
| 41 | 
            -
              _commitFilter( | 
| 42 | 
            -
                 | 
| 43 | 
            -
             | 
| 44 | 
            -
                if ( | 
| 45 | 
            -
                  this._selectNew(query)
         | 
| 46 | 
            -
                } else if (isDeleting) {
         | 
| 41 | 
            +
              _commitFilter(event) {
         | 
| 42 | 
            +
                if (this._shouldTreatAsNewOptionForFiltering(!isDeleteEvent(event))) {
         | 
| 43 | 
            +
                  this._selectNew()
         | 
| 44 | 
            +
                } else if (isDeleteEvent(event)) {
         | 
| 47 45 | 
             
                  this._deselect()
         | 
| 48 46 | 
             
                } else {
         | 
| 49 47 | 
             
                  this._select(this._visibleOptionElements[0])
         | 
| @@ -54,4 +52,8 @@ Combobox.Filtering = Base => class extends Base { | |
| 54 52 | 
             
                await nextFrame()
         | 
| 55 53 | 
             
                callback()
         | 
| 56 54 | 
             
              }
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              get _isQueried() {
         | 
| 57 | 
            +
                return this._actingCombobox.value.length > 0
         | 
| 58 | 
            +
              }
         | 
| 57 59 | 
             
            }
         | 
| @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            import Combobox from "hw_combobox/models/combobox/base"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Combobox.NewOptions = Base => class extends Base {
         | 
| 4 | 
            +
              _shouldTreatAsNewOptionForFiltering(queryIsBeingRefined) {
         | 
| 5 | 
            +
                if (queryIsBeingRefined) {
         | 
| 6 | 
            +
                  return this._isNewOptionWithNoPotentialMatches
         | 
| 7 | 
            +
                } else {
         | 
| 8 | 
            +
                  return this._isNewOptionWithPotentialMatches
         | 
| 9 | 
            +
                }
         | 
| 10 | 
            +
              }
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              // If the user is going to keep refining the query, we can't be sure whether
         | 
| 13 | 
            +
              // the option will end up being new or not unless there are no potential matches.
         | 
| 14 | 
            +
              // +_isNewOptionWithNoPotentialMatches+ allows us to make our best guess
         | 
| 15 | 
            +
              // while the state of the combobox is still in flux.
         | 
| 16 | 
            +
              //
         | 
| 17 | 
            +
              // It's okay for the combobox to say it's not new even if it will be eventually,
         | 
| 18 | 
            +
              // as only the final state matters for submission purposes. This method exists
         | 
| 19 | 
            +
              // as a best effort to keep the state accurate as often as we can.
         | 
| 20 | 
            +
              //
         | 
| 21 | 
            +
              // Note that the first visible option is automatically selected as you type.
         | 
| 22 | 
            +
              // So if there's a partial match, it's not a new option at this point.
         | 
| 23 | 
            +
              //
         | 
| 24 | 
            +
              // The final state is locked-in upon closing the combobox via `_isNewOptionWithPotentialMatches`.
         | 
| 25 | 
            +
              get _isNewOptionWithNoPotentialMatches() {
         | 
| 26 | 
            +
                return this._isNewOptionWithPotentialMatches && !this._isPartialAutocompleteMatch
         | 
| 27 | 
            +
              }
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              // If the query is finalized, we don't care that there are potential matches
         | 
| 30 | 
            +
              // because new options can be substrings of existing options.
         | 
| 31 | 
            +
              //
         | 
| 32 | 
            +
              // We can't use `_isNewOptionWithNoPotentialMatches` because that would
         | 
| 33 | 
            +
              // rule out new options that are partial matches.
         | 
| 34 | 
            +
              get _isNewOptionWithPotentialMatches() {
         | 
| 35 | 
            +
                return this._isQueried && this._allowNew && !this._isExactAutocompleteMatch
         | 
| 36 | 
            +
              }
         | 
| 37 | 
            +
            }
         | 
| @@ -1,5 +1,5 @@ | |
| 1 | 
            -
            import Combobox from "models/combobox/base"
         | 
| 2 | 
            -
            import { visible | 
| 1 | 
            +
            import Combobox from "hw_combobox/models/combobox/base"
         | 
| 2 | 
            +
            import { visible } from "hw_combobox/helpers"
         | 
| 3 3 |  | 
| 4 4 | 
             
            Combobox.Options = Base => class extends Base {
         | 
| 5 5 | 
             
              _resetOptions() {
         | 
| @@ -7,14 +7,6 @@ Combobox.Options = Base => class extends Base { | |
| 7 7 | 
             
                this.hiddenFieldTarget.name = this.originalNameValue
         | 
| 8 8 | 
             
              }
         | 
| 9 9 |  | 
| 10 | 
            -
              _isValidNewOption(query, { ignoreAutocomplete = false } = {}) {
         | 
| 11 | 
            -
                const typedValue = this._actingCombobox.value
         | 
| 12 | 
            -
                const autocompletedValue = this._visibleOptionElements[0]?.getAttribute(this.autocompletableAttributeValue)
         | 
| 13 | 
            -
                const insufficientAutocomplete = !autocompletedValue || !startsWith(autocompletedValue, typedValue)
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                return query.length > 0 && this._allowNew && (ignoreAutocomplete || insufficientAutocomplete)
         | 
| 16 | 
            -
              }
         | 
| 17 | 
            -
             | 
| 18 10 | 
             
              get _allowNew() {
         | 
| 19 11 | 
             
                return !!this.nameWhenNewValue
         | 
| 20 12 | 
             
              }
         | 
| @@ -1,9 +1,10 @@ | |
| 1 | 
            -
            import Combobox from "models/combobox/base"
         | 
| 2 | 
            -
            import { wrapAroundAccess } from "helpers"
         | 
| 1 | 
            +
            import Combobox from "hw_combobox/models/combobox/base"
         | 
| 2 | 
            +
            import { wrapAroundAccess, nullEvent } from "hw_combobox/helpers"
         | 
| 3 3 |  | 
| 4 4 | 
             
            Combobox.Selection = Base => class extends Base {
         | 
| 5 5 | 
             
              selectOption(event) {
         | 
| 6 6 | 
             
                this._select(event.currentTarget)
         | 
| 7 | 
            +
                this.filter(event)
         | 
| 7 8 | 
             
                this.close()
         | 
| 8 9 | 
             
              }
         | 
| 9 10 |  | 
| @@ -49,9 +50,9 @@ Combobox.Selection = Base => class extends Base { | |
| 49 50 | 
             
                if (option) this._commitSelection(option, { selected: false })
         | 
| 50 51 | 
             
              }
         | 
| 51 52 |  | 
| 52 | 
            -
              _selectNew( | 
| 53 | 
            +
              _selectNew() {
         | 
| 53 54 | 
             
                this._resetOptions()
         | 
| 54 | 
            -
                this.hiddenFieldTarget.value =  | 
| 55 | 
            +
                this.hiddenFieldTarget.value = this._actingCombobox.value
         | 
| 55 56 | 
             
                this.hiddenFieldTarget.name = this.nameWhenNewValue
         | 
| 56 57 | 
             
              }
         | 
| 57 58 |  | 
| @@ -70,7 +71,18 @@ Combobox.Selection = Base => class extends Base { | |
| 70 71 | 
             
                }
         | 
| 71 72 | 
             
              }
         | 
| 72 73 |  | 
| 74 | 
            +
              _selectFuzzyMatch() {
         | 
| 75 | 
            +
                if (this._isFuzzyMatch) {
         | 
| 76 | 
            +
                  this._select(this._visibleOptionElements[0], { force: true })
         | 
| 77 | 
            +
                  this.filter(nullEvent)
         | 
| 78 | 
            +
                }
         | 
| 79 | 
            +
              }
         | 
| 80 | 
            +
             | 
| 73 81 | 
             
              get _hasValueButNoSelection() {
         | 
| 74 82 | 
             
                return this.hiddenFieldTarget.value && !this._selectedOptionElement
         | 
| 75 83 | 
             
              }
         | 
| 84 | 
            +
             | 
| 85 | 
            +
              get _isFuzzyMatch() {
         | 
| 86 | 
            +
                return this._isQueried && !!this._visibleOptionElements[0] && !this._isNewOptionWithPotentialMatches
         | 
| 87 | 
            +
              }
         | 
| 76 88 | 
             
            }
         | 
| @@ -1,5 +1,5 @@ | |
| 1 | 
            -
            import Combobox from "models/combobox/base"
         | 
| 2 | 
            -
            import { disableBodyScroll, enableBodyScroll } from "vendor/bodyScrollLock"
         | 
| 1 | 
            +
            import Combobox from "hw_combobox/models/combobox/base"
         | 
| 2 | 
            +
            import { disableBodyScroll, enableBodyScroll } from "hw_combobox/vendor/bodyScrollLock"
         | 
| 3 3 |  | 
| 4 4 | 
             
            Combobox.Toggle = Base => class extends Base {
         | 
| 5 5 | 
             
              open() {
         | 
| @@ -51,9 +51,7 @@ Combobox.Toggle = Base => class extends Base { | |
| 51 51 | 
             
              }
         | 
| 52 52 |  | 
| 53 53 | 
             
              _ensureSelection() {
         | 
| 54 | 
            -
                 | 
| 55 | 
            -
                  this._select(this._selectedOptionElement, { force: true })
         | 
| 56 | 
            -
                }
         | 
| 54 | 
            +
                this._selectFuzzyMatch()
         | 
| 57 55 | 
             
              }
         | 
| 58 56 |  | 
| 59 57 | 
             
              _openByFocusing() {
         | 
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            import Combobox from "hw_combobox/models/combobox/base"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import "hw_combobox/models/combobox/actors"
         | 
| 4 | 
            +
            import "hw_combobox/models/combobox/async_loading"
         | 
| 5 | 
            +
            import "hw_combobox/models/combobox/autocomplete"
         | 
| 6 | 
            +
            import "hw_combobox/models/combobox/dialog"
         | 
| 7 | 
            +
            import "hw_combobox/models/combobox/filtering"
         | 
| 8 | 
            +
            import "hw_combobox/models/combobox/navigation"
         | 
| 9 | 
            +
            import "hw_combobox/models/combobox/new_options"
         | 
| 10 | 
            +
            import "hw_combobox/models/combobox/options"
         | 
| 11 | 
            +
            import "hw_combobox/models/combobox/selection"
         | 
| 12 | 
            +
            import "hw_combobox/models/combobox/toggle"
         | 
| 13 | 
            +
            import "hw_combobox/models/combobox/validity"
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            export default Combobox
         | 
| @@ -11,15 +11,15 @@ class HotwireCombobox::Component | |
| 11 11 | 
             
                  form:             nil,
         | 
| 12 12 | 
             
                  id:               nil,
         | 
| 13 13 | 
             
                  input:            {},
         | 
| 14 | 
            +
                  mobile_at:        "640px",
         | 
| 14 15 | 
             
                  name_when_new:    nil,
         | 
| 15 16 | 
             
                  open:             false,
         | 
| 16 17 | 
             
                  options:          [],
         | 
| 17 | 
            -
                  mobile_at:      "640px",
         | 
| 18 18 | 
             
                  value:            nil,
         | 
| 19 19 | 
             
                  **rest
         | 
| 20 20 | 
             
                @view, @autocomplete, @id, @name, @value, @form, @async_src,
         | 
| 21 21 | 
             
                @name_when_new, @open, @data, @mobile_at, @options, @dialog_label =
         | 
| 22 | 
            -
                  view, autocomplete, id, name, value, form, async_src,
         | 
| 22 | 
            +
                  view, autocomplete, id, name.to_s, value, form, async_src,
         | 
| 23 23 | 
             
                  name_when_new, open, data, mobile_at, options, dialog_label
         | 
| 24 24 |  | 
| 25 25 | 
             
                @combobox_attrs = input.reverse_merge(rest).with_indifferent_access
         | 
| @@ -146,8 +146,8 @@ class HotwireCombobox::Component | |
| 146 146 | 
             
                  :association_name
         | 
| 147 147 |  | 
| 148 148 | 
             
                def infer_association_name
         | 
| 149 | 
            -
                  if name. | 
| 150 | 
            -
                    name. | 
| 149 | 
            +
                  if name.include?("_id")
         | 
| 150 | 
            +
                    name.sub(/_id\z/, "")
         | 
| 151 151 | 
             
                  end
         | 
| 152 152 | 
             
                end
         | 
| 153 153 |  | 
| @@ -204,7 +204,13 @@ class HotwireCombobox::Component | |
| 204 204 | 
             
                end
         | 
| 205 205 |  | 
| 206 206 | 
             
                def hidden_field_value
         | 
| 207 | 
            -
                   | 
| 207 | 
            +
                  return value if value
         | 
| 208 | 
            +
             | 
| 209 | 
            +
                  if form&.object&.defined_enums&.try :[], name
         | 
| 210 | 
            +
                    form.object.public_send "#{name}_before_type_cast"
         | 
| 211 | 
            +
                  else
         | 
| 212 | 
            +
                    form&.object&.try name
         | 
| 213 | 
            +
                  end
         | 
| 208 214 | 
             
                end
         | 
| 209 215 |  | 
| 210 216 |  | 
| @@ -21,7 +21,7 @@ module HotwireCombobox | |
| 21 21 |  | 
| 22 22 | 
             
                initializer "hotwire_combobox.importmap", before: "importmap" do |app|
         | 
| 23 23 | 
             
                  if Rails.application.respond_to?(:importmap)
         | 
| 24 | 
            -
                    app.config.importmap.paths << Engine.root.join("config/ | 
| 24 | 
            +
                    app.config.importmap.paths << Engine.root.join("config/hw_importmap.rb")
         | 
| 25 25 | 
             
                  end
         | 
| 26 26 | 
             
                end
         | 
| 27 27 |  | 
| @@ -27,13 +27,8 @@ module HotwireCombobox | |
| 27 27 | 
             
                  if options.first.is_a? HotwireCombobox::Listbox::Option
         | 
| 28 28 | 
             
                    options
         | 
| 29 29 | 
             
                  else
         | 
| 30 | 
            -
                     | 
| 31 | 
            -
             | 
| 32 | 
            -
                    else
         | 
| 33 | 
            -
                      methods[:content]
         | 
| 34 | 
            -
                    end
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                    hw_parse_combobox_options options, **methods.merge(display: display, content: content)
         | 
| 30 | 
            +
                    render_in_proc = ->(object) { render(**render_in.merge(object: object)) } if render_in.present?
         | 
| 31 | 
            +
                    hw_parse_combobox_options options, render_in: render_in_proc, **methods.merge(display: display)
         | 
| 37 32 | 
             
                  end
         | 
| 38 33 | 
             
                end
         | 
| 39 34 | 
             
                hw_alias :hw_combobox_options
         | 
| @@ -46,6 +41,9 @@ module HotwireCombobox | |
| 46 41 | 
             
                end
         | 
| 47 42 | 
             
                hw_alias :hw_paginated_combobox_options
         | 
| 48 43 |  | 
| 44 | 
            +
                alias_method :hw_async_combobox_options, :hw_paginated_combobox_options
         | 
| 45 | 
            +
                hw_alias :hw_async_combobox_options
         | 
| 46 | 
            +
             | 
| 49 47 | 
             
                protected # library use only
         | 
| 50 48 | 
             
                  def hw_listbox_options_id(id)
         | 
| 51 49 | 
             
                    "#{id}-hw-listbox__options"
         | 
| @@ -55,6 +53,16 @@ module HotwireCombobox | |
| 55 53 | 
             
                    "#{id}__hw_combobox_pagination"
         | 
| 56 54 | 
             
                  end
         | 
| 57 55 |  | 
| 56 | 
            +
                  def hw_combobox_next_page_uri(uri, next_page)
         | 
| 57 | 
            +
                    if next_page
         | 
| 58 | 
            +
                      hw_uri_with_params uri, page: next_page, q: params[:q], format: :turbo_stream
         | 
| 59 | 
            +
                    end
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  def hw_combobox_page_stream_action
         | 
| 63 | 
            +
                    params[:page] ? :append : :update
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
             | 
| 58 66 | 
             
                private
         | 
| 59 67 | 
             
                  def hw_extract_options_and_src(options_or_src, render_in)
         | 
| 60 68 | 
             
                    if options_or_src.is_a? String
         | 
| @@ -73,19 +81,36 @@ module HotwireCombobox | |
| 73 81 | 
             
                    url_or_path
         | 
| 74 82 | 
             
                  end
         | 
| 75 83 |  | 
| 76 | 
            -
                  def hw_parse_combobox_options(options, **methods)
         | 
| 84 | 
            +
                  def hw_parse_combobox_options(options, render_in: nil, **methods)
         | 
| 77 85 | 
             
                    options.map do |option|
         | 
| 78 | 
            -
                       | 
| 79 | 
            -
                      HotwireCombobox::Listbox::Option.new **attrs
         | 
| 86 | 
            +
                      HotwireCombobox::Listbox::Option.new **hw_option_attrs_for(option, render_in: render_in, **methods)
         | 
| 80 87 | 
             
                    end
         | 
| 81 88 | 
             
                  end
         | 
| 82 89 |  | 
| 83 | 
            -
                  def  | 
| 84 | 
            -
                     | 
| 85 | 
            -
             | 
| 86 | 
            -
                       | 
| 87 | 
            -
             | 
| 88 | 
            -
                       | 
| 90 | 
            +
                  def hw_option_attrs_for(option, render_in: nil, **methods)
         | 
| 91 | 
            +
                    case option
         | 
| 92 | 
            +
                    when Hash
         | 
| 93 | 
            +
                      option
         | 
| 94 | 
            +
                    when String
         | 
| 95 | 
            +
                      {}.tap do |attrs|
         | 
| 96 | 
            +
                        attrs[:display] = option
         | 
| 97 | 
            +
                        attrs[:value] = option
         | 
| 98 | 
            +
                        attrs[:content] = render_in.(option) if render_in
         | 
| 99 | 
            +
                      end
         | 
| 100 | 
            +
                    when Array
         | 
| 101 | 
            +
                      {}.tap do |attrs|
         | 
| 102 | 
            +
                        attrs[:display] = option.first
         | 
| 103 | 
            +
                        attrs[:value] = option.last
         | 
| 104 | 
            +
                        attrs[:content] = render_in.(option.first) if render_in
         | 
| 105 | 
            +
                      end
         | 
| 106 | 
            +
                    else
         | 
| 107 | 
            +
                      {}.tap do |attrs|
         | 
| 108 | 
            +
                        attrs[:value] = hw_call_method_or_proc(option, methods[:value] || :id)
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                        attrs[:id] = hw_call_method_or_proc(option, methods[:id]) if methods[:id]
         | 
| 111 | 
            +
                        attrs[:display] = hw_call_method_or_proc(option, methods[:display]) if methods[:display]
         | 
| 112 | 
            +
                        attrs[:content] = hw_call_method_or_proc(option, render_in || methods[:content]) if render_in || methods[:content]
         | 
| 113 | 
            +
                      end
         | 
| 89 114 | 
             
                    end
         | 
| 90 115 | 
             
                  end
         | 
| 91 116 |  | 
| @@ -96,15 +121,5 @@ module HotwireCombobox | |
| 96 121 | 
             
                      object.public_send method_or_proc
         | 
| 97 122 | 
             
                    end
         | 
| 98 123 | 
             
                  end
         | 
| 99 | 
            -
             | 
| 100 | 
            -
                  def hw_combobox_next_page_uri(uri, next_page)
         | 
| 101 | 
            -
                    if next_page
         | 
| 102 | 
            -
                      hw_uri_with_params uri, page: next_page, q: params[:q], format: :turbo_stream
         | 
| 103 | 
            -
                    end
         | 
| 104 | 
            -
                  end
         | 
| 105 | 
            -
             | 
| 106 | 
            -
                  def hw_combobox_page_stream_action
         | 
| 107 | 
            -
                    params[:page] ? :append : :update
         | 
| 108 | 
            -
                  end
         | 
| 109 124 | 
             
              end
         | 
| 110 125 | 
             
            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.1. | 
| 4 | 
            +
              version: 0.1.33
         | 
| 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-02- | 
| 11 | 
            +
            date: 2024-02-27 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rails
         | 
| @@ -63,25 +63,23 @@ files: | |
| 63 63 | 
             
            - README.md
         | 
| 64 64 | 
             
            - Rakefile
         | 
| 65 65 | 
             
            - app/assets/config/hw_combobox_manifest.js
         | 
| 66 | 
            -
            - app/assets/javascripts/controllers/application.js
         | 
| 67 66 | 
             
            - app/assets/javascripts/controllers/hw_combobox_controller.js
         | 
| 68 | 
            -
            - app/assets/javascripts/ | 
| 69 | 
            -
            - app/assets/javascripts/ | 
| 70 | 
            -
            - app/assets/javascripts/ | 
| 71 | 
            -
            - app/assets/javascripts/models/combobox.js
         | 
| 72 | 
            -
            - app/assets/javascripts/models/combobox/ | 
| 73 | 
            -
            - app/assets/javascripts/models/combobox/ | 
| 74 | 
            -
            - app/assets/javascripts/models/combobox/ | 
| 75 | 
            -
            - app/assets/javascripts/models/combobox/ | 
| 76 | 
            -
            - app/assets/javascripts/models/combobox/ | 
| 77 | 
            -
            - app/assets/javascripts/models/combobox/ | 
| 78 | 
            -
            - app/assets/javascripts/models/combobox/ | 
| 79 | 
            -
            - app/assets/javascripts/models/combobox/ | 
| 80 | 
            -
            - app/assets/javascripts/models/combobox/ | 
| 81 | 
            -
            - app/assets/javascripts/models/combobox/ | 
| 82 | 
            -
            - app/assets/javascripts/ | 
| 83 | 
            -
            - app/assets/javascripts/vendor/ | 
| 84 | 
            -
            - app/assets/javascripts/vendor/requestjs.js
         | 
| 67 | 
            +
            - app/assets/javascripts/hw_combobox/helpers.js
         | 
| 68 | 
            +
            - app/assets/javascripts/hw_combobox/models/combobox.js
         | 
| 69 | 
            +
            - app/assets/javascripts/hw_combobox/models/combobox/actors.js
         | 
| 70 | 
            +
            - app/assets/javascripts/hw_combobox/models/combobox/async_loading.js
         | 
| 71 | 
            +
            - app/assets/javascripts/hw_combobox/models/combobox/autocomplete.js
         | 
| 72 | 
            +
            - app/assets/javascripts/hw_combobox/models/combobox/base.js
         | 
| 73 | 
            +
            - app/assets/javascripts/hw_combobox/models/combobox/dialog.js
         | 
| 74 | 
            +
            - app/assets/javascripts/hw_combobox/models/combobox/filtering.js
         | 
| 75 | 
            +
            - app/assets/javascripts/hw_combobox/models/combobox/navigation.js
         | 
| 76 | 
            +
            - app/assets/javascripts/hw_combobox/models/combobox/new_options.js
         | 
| 77 | 
            +
            - app/assets/javascripts/hw_combobox/models/combobox/options.js
         | 
| 78 | 
            +
            - app/assets/javascripts/hw_combobox/models/combobox/selection.js
         | 
| 79 | 
            +
            - app/assets/javascripts/hw_combobox/models/combobox/toggle.js
         | 
| 80 | 
            +
            - app/assets/javascripts/hw_combobox/models/combobox/validity.js
         | 
| 81 | 
            +
            - app/assets/javascripts/hw_combobox/vendor/bodyScrollLock.js
         | 
| 82 | 
            +
            - app/assets/javascripts/hw_combobox/vendor/requestjs.js
         | 
| 85 83 | 
             
            - app/assets/stylesheets/hotwire_combobox.css
         | 
| 86 84 | 
             
            - app/presenters/hotwire_combobox/component.rb
         | 
| 87 85 | 
             
            - app/presenters/hotwire_combobox/listbox/option.rb
         | 
| @@ -93,7 +91,7 @@ files: | |
| 93 91 | 
             
            - app/views/hotwire_combobox/combobox/_hidden_field.html.erb
         | 
| 94 92 | 
             
            - app/views/hotwire_combobox/combobox/_input.html.erb
         | 
| 95 93 | 
             
            - app/views/hotwire_combobox/combobox/_paginated_listbox.html.erb
         | 
| 96 | 
            -
            - config/ | 
| 94 | 
            +
            - config/hw_importmap.rb
         | 
| 97 95 | 
             
            - lib/hotwire_combobox.rb
         | 
| 98 96 | 
             
            - lib/hotwire_combobox/engine.rb
         | 
| 99 97 | 
             
            - lib/hotwire_combobox/helper.rb
         | 
| @@ -120,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 120 118 | 
             
                - !ruby/object:Gem::Version
         | 
| 121 119 | 
             
                  version: '0'
         | 
| 122 120 | 
             
            requirements: []
         | 
| 123 | 
            -
            rubygems_version: 3. | 
| 121 | 
            +
            rubygems_version: 3.5.6
         | 
| 124 122 | 
             
            signing_key:
         | 
| 125 123 | 
             
            specification_version: 4
         | 
| 126 124 | 
             
            summary: Autocomplete for Rails apps using Hotwire
         | 
| @@ -1 +0,0 @@ | |
| 1 | 
            -
            import "controllers"
         | 
| @@ -1,14 +0,0 @@ | |
| 1 | 
            -
            import Combobox from "models/combobox/base"
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            import "models/combobox/actors"
         | 
| 4 | 
            -
            import "models/combobox/async_loading"
         | 
| 5 | 
            -
            import "models/combobox/autocomplete"
         | 
| 6 | 
            -
            import "models/combobox/dialog"
         | 
| 7 | 
            -
            import "models/combobox/filtering"
         | 
| 8 | 
            -
            import "models/combobox/navigation"
         | 
| 9 | 
            -
            import "models/combobox/options"
         | 
| 10 | 
            -
            import "models/combobox/selection"
         | 
| 11 | 
            -
            import "models/combobox/toggle"
         | 
| 12 | 
            -
            import "models/combobox/validity"
         | 
| 13 | 
            -
             | 
| 14 | 
            -
            export default Combobox
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         |