Create SelectorWithFilter component

This commit is contained in:
Jean-Baptiste Bellet
2022-03-22 10:42:36 +01:00
parent d4cfa7b368
commit 1adb22be71
6 changed files with 192 additions and 0 deletions

View File

@@ -11,6 +11,7 @@ class SelectorComponent < ViewComponentReflex::Component
selected: selected.include?(item[:value])
}
end
@selected = selected
@state = :close
@data = data
end

View File

@@ -0,0 +1,24 @@
# frozen_string_literal: true
class SuperSelectorComponent < SelectorComponent
def initialize(title:, selected:, items:, data: {})
super(title: title, selected: selected, items: items, data: data)
@query = ""
@selected_items = items.select { |item| @selected.include?(item[:value]) }
filter_items
end
def search
@query = element.value
filter_items
end
def filter_items
@filtered_items = if @query.empty?
@items
else
@items.select { |item| item[:label].downcase.include?(@query.downcase) }
end
end
end

View File

@@ -0,0 +1,22 @@
= component_controller do
.super-selector{ class: ("super-selector-close" if @state == :close) }
.super-selector-main
.super-selector-label
= @title
.super-selector-selected-items
- case @selected_items.length
- when 1, 2
- @selected_items.each do |item|
.super-selector-selected-item
= item[:label]
- else
.super-selector-selected-item
= "#{@selected_items.length} categories selected"
.super-selector-arrow{data: reflex_data_attributes(:toggle)}
.super-selector-wrapper
.super-selector-search
%input{type: "text", placeholder: "Search", data: reflex_data_attributes("debounced:input->search"), value: @query}
.super-selector-items
- @filtered_items.each do |item|
.super-selector-item{ class: ("selected" if item[:selected]), data: @data, "data-value": item[:value] }
= item[:label]

View File

@@ -0,0 +1,126 @@
.super-selector {
margin-top: 5px;
position: relative;
.super-selector-main {
border: 1px solid #d2d2d2;
height: 3em;
position: relative;
.super-selector-label {
padding-left: 5px;
padding-right: 5px;
margin-left: 10px;
position: absolute;
top: -1em;
background-color: white;
}
.super-selector-arrow {
position: absolute;
right: 0px;
height: 3em;
width: 1.5em;
top: -1px;
cursor: pointer;
&:after {
content: "";
position: absolute;
top: 50%;
right: 5px;
margin-top: -5px;
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #d2d2d2;
}
}
}
.super-selector-selected-items {
margin-left: 5px;
margin-right: 2em;
margin-top: 7px;
display: flex;
.super-selector-selected-item {
border: 1px solid #cee1f4;
background-color: #eff5fc;
border-radius: 20px;
height: 2em;
padding-left: 10px;
padding-right: 10px;
display: inline-block;
margin-right: 5px;
padding-top: 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.super-selector-wrapper {
position: absolute;
left: 0px;
right: 0px;
z-index: 1;
background-color: white;
margin-top: -1px;
border: 1px solid #d2d2d2;
.super-selector-search {
border-bottom: 1px solid #d2d2d2;
padding: 10px 5px;
input {
border: 1px solid #d2d2d2;
box-sizing: border-box;
border-radius: 4px;
width: 100%;
}
}
.super-selector-items {
overflow-y: auto;
min-height: 6em;
.super-selector-item {
padding-left: 10px;
padding-right: 10px;
border-bottom: 1px solid #d2d2d2;
position: relative;
height: 3em;
line-height: 3em;
&:hover {
background-color: #eee;
cursor: pointer;
}
&:last-child {
border-bottom: none;
}
&.selected {
&:after {
content: "";
display: inline-block;
position: absolute;
right: 10px;
}
}
}
}
}
}
.super-selector-close {
&.super-selector {
.super-selector-wrapper {
display: none;
}
}
}

View File

@@ -0,0 +1,18 @@
import ApplicationController from "./application_controller";
export default class extends ApplicationController {
connect() {
super.connect();
window.addEventListener("click", this.handleClick);
}
disconnect() {
super.disconnect();
window.removeEventListener("click", this.handleClick);
}
handleClick = (event) => {
if (!this.element.contains(event.target)) {
this.stimulate("SuperSelectorComponent#close", this.element);
}
};
}

View File

@@ -123,5 +123,6 @@
@import "app/components/product_component/product_component";
@import "app/components/selector_component/selector_component";
@import "app/components/products_table_component/products_table_component";
@import "app/components/super_selector_component/super_selector_component";
@import "v2/main.scss";