All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.patternfly.component.label.LabelGroup Maven / Gradle / Ivy

There is a newer version: 0.2.11
Show newest version
/*
 *  Copyright 2023 Red Hat
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.patternfly.component.label;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.jboss.elemento.Attachable;
import org.jboss.elemento.ButtonType;
import org.jboss.elemento.Elements;
import org.jboss.elemento.Id;
import org.patternfly.component.BaseComponent;
import org.patternfly.component.Closeable;
import org.patternfly.component.ComponentType;
import org.patternfly.component.HasItems;
import org.patternfly.component.button.Button;
import org.patternfly.component.tooltip.TooltipToggle;
import org.patternfly.core.Aria;
import org.patternfly.core.Roles;
import org.patternfly.handler.CloseHandler;
import org.patternfly.style.Classes;
import org.patternfly.style.Color;
import org.patternfly.style.Modifiers.Vertical;

import elemental2.dom.Element;
import elemental2.dom.Event;
import elemental2.dom.HTMLDivElement;
import elemental2.dom.HTMLElement;
import elemental2.dom.HTMLLIElement;
import elemental2.dom.MutationRecord;

import static org.jboss.elemento.Elements.div;
import static org.jboss.elemento.Elements.failSafeRemoveFromParent;
import static org.jboss.elemento.Elements.insertBefore;
import static org.jboss.elemento.Elements.li;
import static org.jboss.elemento.Elements.removeChildrenFrom;
import static org.jboss.elemento.Elements.setVisible;
import static org.jboss.elemento.Elements.span;
import static org.jboss.elemento.Elements.ul;
import static org.jboss.elemento.EventType.click;
import static org.patternfly.component.button.Button.button;
import static org.patternfly.core.Aria.hidden;
import static org.patternfly.core.Aria.label;
import static org.patternfly.core.Aria.labelledBy;
import static org.patternfly.core.Attributes.role;
import static org.patternfly.handler.CloseHandler.fireEvent;
import static org.patternfly.handler.CloseHandler.shouldClose;
import static org.patternfly.icon.IconSets.fas.timesCircle;
import static org.patternfly.style.Classes.chipGroup;
import static org.patternfly.style.Classes.close;
import static org.patternfly.style.Classes.component;
import static org.patternfly.style.Classes.item;
import static org.patternfly.style.Classes.labelGroup;
import static org.patternfly.style.Classes.list;
import static org.patternfly.style.Classes.main;
import static org.patternfly.style.Classes.modifier;
import static org.patternfly.style.Classes.overflow;

public class LabelGroup extends BaseComponent implements
        Closeable,
        HasItems,
        Vertical,
        Attachable {

    // ------------------------------------------------------ factory

    public static LabelGroup labelGroup() {
        return new LabelGroup(null);
    }

    public static LabelGroup labelGroup(String category) {
        return new LabelGroup(category);
    }

    // ------------------------------------------------------ instance

    private static final int DEFAULT_NUM_CHIPS = 3;
    private static final String REMAINING_PLACEHOLDER = "${remaining}";

    private final HTMLElement listElement;
    private final Map items;
    private final List> closeHandler;
    private boolean expanded;
    private int numLabels;
    private String collapsedText;
    private String expandedText;
    private Label overflowLabel;
    private Button closeButton;
    private HTMLElement categoryElement;
    private HTMLElement overflowItem;
    private TooltipToggle tooltipToggle;

    LabelGroup(String category) {
        super(ComponentType.ChipGroup, div().css(component(labelGroup)).element());
        this.items = new LinkedHashMap<>();
        this.closeHandler = new ArrayList<>();
        this.expanded = false;
        this.numLabels = DEFAULT_NUM_CHIPS;
        this.collapsedText = REMAINING_PLACEHOLDER + " more";
        this.expandedText = "Show less";

        add(div().css(component(labelGroup, main))
                .add(listElement = ul().css(component(labelGroup, list))
                        .attr(role, Roles.list)
                        .element()));
        if (category != null) {
            category(category);
        } else {
            listElement.setAttribute(label, "Label group category");
        }
        storeComponent();
        Attachable.register(this, this);
    }

    @Override
    public void attach(MutationRecord mutationRecord) {
        if (tooltipToggle != null) {
            tooltipToggle.eval();
        }
    }

    @Override
    public void detach(MutationRecord mutationRecord) {
        if (tooltipToggle != null) {
            tooltipToggle.stop();
        }
    }

    // ------------------------------------------------------ add

    @Override
    public LabelGroup add(Label label) {
        items.put(label.identifier(), label);

        HTMLLIElement itemElement = li().css(component(labelGroup, list, item))
                .add(label)
                .element();
        if (overflowItem != null) {
            insertBefore(itemElement, overflowItem);
        } else {
            listElement.appendChild(itemElement);
        }

        overflow();
        return this;
    }

    // ------------------------------------------------------ builder

    public LabelGroup category(String category) {
        if (categoryElement == null) {
            css(modifier(Classes.category));
            String categoryId = Id.unique(componentType().id, "category");
            categoryElement = span().css(component(labelGroup, Classes.label))
                    .id(categoryId)
                    .aria(hidden, true)
                    .element();
            insertBefore(categoryElement, listElement);
            listElement.setAttribute(labelledBy, categoryId);
            tooltipToggle = new TooltipToggle(categoryElement);
        }
        categoryElement.textContent = category;
        return this;
    }

    public LabelGroup numLabels(int numLabels) {
        if (numLabels > 0) {
            this.numLabels = numLabels;
        }
        return this;
    }

    public LabelGroup closable() {
        return closable(null);
    }

    public LabelGroup closable(CloseHandler closeHandler) {
        this.closeHandler.add(closeHandler);

        String closeId = Id.unique(componentType().id, "close");
        String labelledBy = closeId;
        if (categoryElement != null) {
            labelledBy += " " + categoryElement.id;
        }

        add(div().css(component(labelGroup, close))
                .add(closeButton = button()
                        .plain()
                        .icon(timesCircle())
                        .id(closeId)
                        .aria(Aria.label, "Close label group")
                        .aria(Aria.labelledBy, labelledBy)
                        .on(click, event -> close(event, true))));
        return this;
    }

    public LabelGroup collapsedText(String collapsedText) {
        this.collapsedText = collapsedText;
        return this;
    }

    public LabelGroup expandedText(String expandedText) {
        this.expandedText = expandedText;
        return this;
    }

    @Override
    public LabelGroup that() {
        return this;
    }

    // ------------------------------------------------------ aria

    public LabelGroup ariaCloseLabel(String label) {
        if (closeButton != null) {
            closeButton.aria(Aria.label, label);
        }
        return this;
    }

    // ------------------------------------------------------ events

    @Override
    public LabelGroup onClose(CloseHandler closeHandler) {
        if (closeHandler != null) {
            this.closeHandler.add(closeHandler);
        }
        return this;
    }

    // ------------------------------------------------------ api

    @Override
    public void close(Event event, boolean fireEvent) {
        if (shouldClose(this, closeHandler, event, fireEvent)) {
            failSafeRemoveFromParent(this);
            fireEvent(this, closeHandler, event, fireEvent);
        }
    }

    @Override
    public Iterator




© 2015 - 2024 Weber Informatics LLC | Privacy Policy