Class: Shadcn::Combobox::Component

Inherits:
ApplicationViewComponent show all
Defined in:
app/components/shadcn/combobox/component.rb

Overview

Port of registry/new-york-v4/ui/combobox.tsx — the one file of the 61 that is written against Base UI rather than Radix.

That is the whole story of this port, and it is visible in the class strings: data-open:, data-closed:, --anchor-width, --available-height. Every other family here emits data-state="open" and reads --radix-*. Reproducing upstream's classes therefore means emitting Base UI's conventions in this family and nowhere else — which is what this does, and what popper.js publishes the four unprefixed variables for. See features/combobox.md.

The root itself renders nothing upstream (const Combobox = ComboboxPrimitive.Root, a context provider), so it is a display: contents wrapper here — the same shape every context-only root in this gem takes.

Constant Summary

Constants inherited from ApplicationViewComponent

ApplicationViewComponent::CONTENTS_STYLE, ApplicationViewComponent::VOID_TAGS

Instance Attribute Summary collapse

Attributes inherited from ApplicationViewComponent

#attributes

Instance Method Summary collapse

Methods inherited from ApplicationViewComponent

#css_classes, default_tag, #merged_style, #render_element, #shadcn_t, slot_name, #style_variants, #tag_name

Constructor Details

#initialize(name: nil, value: nil, label: nil, multiple: false, **attributes) ⇒ Component

name: submits with the form, as every other control in this gem does through a hidden input; value: is what is chosen and label: what is shown for it.

multiple: is Base UI's own prop — "Whether multiple items can be selected" — and, as there, value: then takes an array. It submits the way Rails expects a collection to: name gains [] and there is one hidden input per chosen value, so params[:post][:tag_ids] is an array with no parsing on the receiving end.



46
47
48
49
50
51
52
# File 'app/components/shadcn/combobox/component.rb', line 46

def initialize(name: nil, value: nil, label: nil, multiple: false, **attributes)
  @name = name
  @multiple = multiple
  @values = Array.wrap(value).map(&:to_s).reject(&:blank?)
  @label = label
  super(**attributes)
end

Instance Attribute Details

#labelObject (readonly)

Returns the value of attribute label.



35
36
37
# File 'app/components/shadcn/combobox/component.rb', line 35

def label
  @label
end

#multipleObject (readonly)

Returns the value of attribute multiple.



35
36
37
# File 'app/components/shadcn/combobox/component.rb', line 35

def multiple
  @multiple
end

#nameObject (readonly)

Returns the value of attribute name.



35
36
37
# File 'app/components/shadcn/combobox/component.rb', line 35

def name
  @name
end

Instance Method Details

#callObject



78
79
80
# File 'app/components/shadcn/combobox/component.rb', line 78

def call
  render_element(body: safe_join([ combobox_input, combobox_chips, combobox_content, *hidden_inputs ].compact))
end

#element_attributes(**defaults) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'app/components/shadcn/combobox/component.rb', line 64

def element_attributes(**defaults)
  super(**{
    style: merged_style("display:contents"),
    "data-controller" => "shadcn--combobox",
    "data-shadcn--combobox-value-value" => value,
    "data-shadcn--combobox-multiple-value" => (multiple.presence && "true"),
    "data-shadcn--combobox-values-value" => (values.to_json if multiple),
    # The controller writes the hidden inputs as chips come and go, and
    # needs a name to write them under. Kept off the DOM when there is no
    # name, like the inputs themselves.
    "data-shadcn--combobox-name-value" => (field_name if multiple && name.present?)
  }.compact.merge(defaults))
end

#valueObject

The single chosen value. In multiple mode there is no such thing, and the controller reads values instead.



56
57
58
# File 'app/components/shadcn/combobox/component.rb', line 56

def value
  multiple ? nil : @values.first
end

#valuesObject



60
61
62
# File 'app/components/shadcn/combobox/component.rb', line 60

def values
  @values
end