# frozen_string_literal: true module Ariadne # Use `CounterComponent` to add a count to navigational elements and buttons. # # @accessibility # Always use `CounterComponent` with adjacent text that provides supplementary information regarding what the count is for. For instance, `Counter` # should be accompanied with text such as `issues` or `pull requests`. # class CounterComponent < Ariadne::Component DEFAULT_CLASSES = "ariadne-inline-flex ariadne-items-center ariadne-p-1 ariadne-border ariadne-border-transparent ariadne-rounded-full ariadne-shadow-sm focus:ariadne-outline-none focus:ariadne-ring-2 focus:ariadne-ring-offset-2" # @example Default # <%= render(Ariadne::CounterComponent.new(count: 25)) %> # # @example Schemes # <%= render(Ariadne::CounterComponent.new(count: 25)) %> # <%= render(Ariadne::CounterComponent.new(count: 25)) %> # # @param tag [Symbol, String] The rendered tag name # @param classes [String] <%= link_to_classes_docs %> # @param count [Integer, Float::INFINITY, nil] The number to be displayed (e.x. # of issues, pull requests) # @param limit [Integer, nil] Maximum value to display. Pass `nil` for no limit. (e.x. if `count` == 6,000 and `limit` == 5000, counter will display "5,000+") # @param hide_if_zero [Boolean] If true, a `hidden` attribute is added to the counter if `count` is zero. # @param text [String] Text to display instead of count. # @param round [Boolean] Whether to apply rounding logic to value. # @param attributes [Hash] <%= link_to_attributes_docs %> def initialize( tag: :span, count: 0, limit: 9_000, hide_if_zero: false, text: "", round: false, classes: "", attributes: {} ) @count = count @limit = limit @hide_if_zero = hide_if_zero @text = text @round = round @attributes = attributes @has_limit = !@limit.nil? @tag = check_incoming_tag(:span, tag) @attributes[:title] = title @classes = class_names( DEFAULT_CLASSES, classes ) @attributes[:hidden] = true if count == 0 && hide_if_zero end def call render(Ariadne::BaseComponent.new(tag: @tag, classes: @classes, attributes: @attributes)) { value } end private def title if @text.present? @text elsif @count.nil? "Not available" elsif @count == Float::INFINITY "Infinity" else count = @count.to_i str = number_with_delimiter(@has_limit ? [count, @limit].min : count) str += "+" if @has_limit && count > @limit str end end private def value if @text.present? @text elsif @count.nil? "" # CSS will hide it elsif @count == Float::INFINITY "∞" else if @round count = @has_limit ? [@count.to_i, @limit].min : @count.to_i precision = count.between?(100_000, 999_999) ? 0 : 1 units = { thousand: "k", million: "m", billion: "b" } str = number_to_human(count, precision: precision, significant: false, units: units, format: "%n%u") else @count = @count.to_i str = number_with_delimiter(@has_limit ? [@count, @limit].min : @count) end str += "+" if @has_limit && @count.to_i > @limit str end end end end