Module: Clsx::Helper

Included in:
Clsx
Defined in:
lib/clsx/helper.rb,
lib/clsx/tailwind_merge.rb

Overview

Adds the merged #twm variant to the Helper mixin.

Constant Summary collapse

TAB_OR_NEWLINE =

Single-pass scan for tab/newline. Collapses two consecutive include? scans into one regex match (no MatchData alloc). Space is checked separately first so the common "has a space" case still short-circuits.

/[\t\n]/

Instance Method Summary collapse

Instance Method Details

#clsx(*args) ⇒ String? Also known as: cn

Build a CSS class string from an arbitrary mix of arguments.

Falsy values (+nil+, false) and standalone true are discarded. Duplicates are eliminated. Returns nil (not "") when no classes apply.

Examples:

Strings and hashes

clsx('foo', 'bar')                      # => "foo bar"
clsx(foo: true, bar: false, baz: true)  # => "foo baz"

Nested arrays

clsx('a', ['b', nil, ['c']])            # => "a b c"
clsx(%w[foo bar], hidden: true)         # => "foo bar hidden"

Parameters:

  • args (String, Symbol, Hash, Array, Numeric, nil, false)

    class descriptors to merge into a single space-separated string

Returns:

  • (String)

    space-joined class string

  • (nil)

    when no classes apply



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/clsx/helper.rb', line 32

def clsx(*args)
  return nil if args.empty?

  if args.size == 1
    arg = args[0]
    # Inline the two dominant single-arg shapes (String, Hash) so they skip
    # the clsx_one dispatch. Other types fall through to clsx_one, which no
    # longer re-checks String or Hash (already ruled out here).
    if arg.is_a?(String)
      return nil if arg.empty?
      return arg unless arg.include?(' ') || arg.match?(TAB_OR_NEWLINE)

      return clsx_dedup_str(arg)
    end

    return clsx_hash(arg) if arg.is_a?(Hash)

    return clsx_one(arg)
  end

  if args.size == 2 && args[0].is_a?(String) && args[1].is_a?(Hash)
    str = args[0]
    return clsx_hash(args[1]) if str.empty?
    return clsx_str_hash_full(str, args[1]) if str.include?(' ') || str.match?(TAB_OR_NEWLINE)

    return clsx_str_hash(str, args[1])
  end

  seen = {}
  clsx_walk(args, seen)
  clsx_join(seen)
end

#twmString?

Like #clsx, but pipes the result through Clsx.merger to resolve conflicting Tailwind utilities. Returns nil (skipping the merger) when no classes apply, matching #clsx.

Examples:

twm('px-2 px-4')                 # => "px-4"
twm('px-2', 'px-4', hidden: c)   # => "px-4"

Returns:

  • (String, nil)


50
51
52
53
# File 'lib/clsx/tailwind_merge.rb', line 50

def twm(*)
  classes = clsx(*)
  classes && Clsx.merger.merge(classes)
end