protos 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -5
  3. data/CHANGELOG.md +11 -0
  4. data/README.md +26 -7
  5. data/benchmarks/.keep +0 -0
  6. data/benchmarks/table.txt +12 -0
  7. data/examples/list.rb +2 -0
  8. data/lib/protos/accordion/item.rb +5 -6
  9. data/lib/protos/accordion.rb +6 -10
  10. data/lib/protos/alert/actions.rb +2 -2
  11. data/lib/protos/alert/icon.rb +2 -2
  12. data/lib/protos/alert.rb +4 -8
  13. data/lib/protos/attributes.rb +7 -8
  14. data/lib/protos/breadcrumbs/crumb.rb +2 -2
  15. data/lib/protos/breadcrumbs.rb +1 -3
  16. data/lib/protos/card/actions.rb +2 -2
  17. data/lib/protos/card/body.rb +2 -2
  18. data/lib/protos/card/image.rb +2 -2
  19. data/lib/protos/card/title.rb +2 -2
  20. data/lib/protos/card.rb +6 -14
  21. data/lib/protos/carousel/actions.rb +2 -2
  22. data/lib/protos/carousel/item.rb +2 -2
  23. data/lib/protos/carousel.rb +4 -8
  24. data/lib/protos/chat_bubble/content.rb +2 -2
  25. data/lib/protos/chat_bubble/footer.rb +2 -2
  26. data/lib/protos/chat_bubble/header.rb +2 -2
  27. data/lib/protos/chat_bubble/image.rb +2 -2
  28. data/lib/protos/chat_bubble.rb +6 -14
  29. data/lib/protos/collapse/content.rb +2 -2
  30. data/lib/protos/collapse/title.rb +3 -3
  31. data/lib/protos/collapse.rb +2 -6
  32. data/lib/protos/combobox.rb +8 -24
  33. data/lib/protos/command/empty.rb +2 -2
  34. data/lib/protos/command/item.rb +2 -2
  35. data/lib/protos/command/list.rb +2 -2
  36. data/lib/protos/command/title.rb +2 -2
  37. data/lib/protos/command/trigger.rb +2 -2
  38. data/lib/protos/command.rb +10 -26
  39. data/lib/protos/component.rb +21 -30
  40. data/lib/protos/drawer/content.rb +2 -2
  41. data/lib/protos/drawer/trigger.rb +2 -2
  42. data/lib/protos/drawer.rb +3 -9
  43. data/lib/protos/dropdown/item.rb +2 -2
  44. data/lib/protos/dropdown.rb +3 -9
  45. data/lib/protos/hero/content.rb +2 -2
  46. data/lib/protos/hero/overlay.rb +2 -2
  47. data/lib/protos/hero.rb +4 -8
  48. data/lib/protos/list/item.rb +2 -2
  49. data/lib/protos/list.rb +3 -5
  50. data/lib/protos/modal/trigger.rb +2 -2
  51. data/lib/protos/modal.rb +5 -11
  52. data/lib/protos/popover/content.rb +2 -0
  53. data/lib/protos/popover/trigger.rb +2 -2
  54. data/lib/protos/popover.rb +4 -8
  55. data/lib/protos/stats/actions.rb +2 -2
  56. data/lib/protos/stats/description.rb +2 -2
  57. data/lib/protos/stats/figure.rb +2 -2
  58. data/lib/protos/stats/stat.rb +2 -2
  59. data/lib/protos/stats/title.rb +2 -2
  60. data/lib/protos/stats/value.rb +2 -2
  61. data/lib/protos/stats.rb +8 -20
  62. data/lib/protos/swap/off.rb +2 -2
  63. data/lib/protos/swap/on.rb +2 -2
  64. data/lib/protos/swap.rb +2 -6
  65. data/lib/protos/table/body.rb +2 -2
  66. data/lib/protos/table/caption.rb +3 -3
  67. data/lib/protos/table/cell.rb +2 -2
  68. data/lib/protos/table/footer.rb +2 -2
  69. data/lib/protos/table/head.rb +2 -2
  70. data/lib/protos/table/header.rb +2 -2
  71. data/lib/protos/table/row.rb +2 -2
  72. data/lib/protos/table.rb +7 -21
  73. data/lib/protos/tabs/tab.rb +3 -3
  74. data/lib/protos/tabs.rb +3 -5
  75. data/lib/protos/theme.rb +38 -45
  76. data/lib/protos/timeline/center.rb +2 -2
  77. data/lib/protos/timeline/item.rb +2 -2
  78. data/lib/protos/timeline/left.rb +2 -2
  79. data/lib/protos/timeline/right.rb +2 -2
  80. data/lib/protos/timeline.rb +6 -14
  81. data/lib/protos/toast/close_button.rb +1 -0
  82. data/lib/protos/toast.rb +3 -5
  83. data/lib/protos/token_list.rb +18 -31
  84. data/lib/protos/typography/heading.rb +2 -2
  85. data/lib/protos/typography/inline_link.rb +3 -3
  86. data/lib/protos/typography/paragraph.rb +2 -2
  87. data/lib/protos/typography.rb +12 -12
  88. data/lib/protos/version.rb +1 -1
  89. data/protos.gemspec +14 -2
  90. metadata +6 -4
@@ -5,12 +5,12 @@ module Protos
5
5
  class Tab < Component
6
6
  # DOCS: A single tab in a tabs component
7
7
 
8
- param :id
8
+ option :id
9
9
  option :label
10
10
  option :active, default: -> { false }
11
11
  option :disabled, default: -> { false }
12
12
 
13
- def view_template(&block)
13
+ def view_template(&)
14
14
  input(
15
15
  type: :radio,
16
16
  class: css[:input],
@@ -19,7 +19,7 @@ module Protos
19
19
  aria_label: label,
20
20
  autocomplete: :off
21
21
  )
22
- div(**attrs, &block)
22
+ div(**attrs, &)
23
23
  end
24
24
 
25
25
  private
data/lib/protos/tabs.rb CHANGED
@@ -24,13 +24,11 @@ module Protos
24
24
  :lg
25
25
  )
26
26
 
27
- def view_template(&block)
28
- div(**attrs, &block)
27
+ def view_template(&)
28
+ div(**attrs, &)
29
29
  end
30
30
 
31
- def tab(...)
32
- Tab.new(...)
33
- end
31
+ def tab(...) = render Tab.new(...)
34
32
 
35
33
  private
36
34
 
data/lib/protos/theme.rb CHANGED
@@ -13,13 +13,24 @@ module Protos
13
13
  end
14
14
  end
15
15
 
16
- def initialize(theme = {}, **kwargs)
17
- @theme = theme.merge(kwargs)
16
+ def initialize(theme = {}, tailwind_merge: true, **kwargs)
17
+ @tailwind_merge = tailwind_merge
18
+
19
+ @theme = Hash.new do |hash, key|
20
+ hash[key] = TokenList.new
21
+ end
22
+
23
+ theme.merge!(kwargs).each do |key, value|
24
+ @theme[key].add(value)
25
+ end
18
26
  end
19
27
 
20
28
  def [](key)
21
- value = @theme[key]
22
- return value unless value.is_a?(String)
29
+ return nil unless key?(key)
30
+
31
+ value = @theme[key].to_s
32
+ return nil if value.empty?
33
+ return value unless @tailwind_merge
23
34
 
24
35
  self.class.merger.merge(value)
25
36
  end
@@ -29,66 +40,48 @@ module Protos
29
40
  end
30
41
 
31
42
  def add(key, value)
32
- TokenList.new
33
- .add(@theme.fetch(key, ""))
34
- .add(value)
35
- .to_s
36
- .tap do |tokens|
37
- @theme[key] = tokens
38
- end
43
+ return if value.nil?
44
+
45
+ @theme[key].add(value)
39
46
  end
40
47
 
41
48
  def remove(key, value)
42
- TokenList.new
43
- .add(@theme.fetch(key, ""))
44
- .remove(value)
45
- .to_s
46
- .tap do |tokens|
47
- @theme[key] = tokens
48
- end
49
+ @theme[key].remove(value)
50
+ @theme.delete(key) if @theme[key].empty?
49
51
  end
50
52
 
51
53
  def set(key, value)
52
- if value.is_a?(Hash)
53
- @theme[key] = value
54
- else
55
- TokenList
56
- .parse(value)
57
- .to_s
58
- .tap do |tokens|
59
- @theme[key] = tokens
60
- end
61
- end
54
+ return if value.nil?
55
+
56
+ @theme[key].clear.add(value)
62
57
  end
63
58
 
64
59
  def merge(hash)
65
- hash ||= {}
66
-
67
- tap do
68
- hash.each_key do |key|
69
- if key?(key)
70
- add(key, hash[key])
71
- elsif negation?(key)
72
- no_bang = key.to_s[1..].to_sym
73
- remove(no_bang, hash[key])
74
- elsif override?(key)
75
- no_bang = key.to_s.chomp("!").to_sym
76
- set(no_bang, hash[key])
77
- else
78
- set(key, hash[key])
79
- end
60
+ return self unless hash
61
+
62
+ hash.each do |key, value|
63
+ if key?(key)
64
+ add(key, value)
65
+ elsif negation?(key)
66
+ remove(key[1..].to_sym, value)
67
+ elsif override?(key)
68
+ set(key[..-2].to_sym, value)
69
+ else
70
+ set(key, value)
80
71
  end
81
72
  end
73
+
74
+ self
82
75
  end
83
76
 
84
77
  private
85
78
 
86
79
  def negation?(key)
87
- key.to_s.start_with?("!")
80
+ key.start_with?("!")
88
81
  end
89
82
 
90
83
  def override?(key)
91
- key.to_s.end_with?("!")
84
+ key.end_with?("!")
92
85
  end
93
86
  end
94
87
  end
@@ -6,8 +6,8 @@ module Protos
6
6
  # DOCS: The center of a timeline. This would usually be an icon or
7
7
  # something small that shows a point on the timeline.
8
8
 
9
- def view_template(&block)
10
- div(**attrs, &block)
9
+ def view_template(&)
10
+ div(**attrs, &)
11
11
  end
12
12
 
13
13
  private
@@ -7,8 +7,8 @@ module Protos
7
7
  # right and depending on its position in the list, an hr at the beginning
8
8
  # or end.
9
9
 
10
- def view_template(&block)
11
- li(**attrs, &block)
10
+ def view_template(&)
11
+ li(**attrs, &)
12
12
  end
13
13
  end
14
14
  end
@@ -6,8 +6,8 @@ module Protos
6
6
  # DOCS: Content on the left (on daisyui "start") side of a timeline.
7
7
  # We chose not to use start/end because of the keywork conflict with ruby.
8
8
 
9
- def view_template(&block)
10
- div(**attrs, &block)
9
+ def view_template(&)
10
+ div(**attrs, &)
11
11
  end
12
12
 
13
13
  private
@@ -6,8 +6,8 @@ module Protos
6
6
  # DOCS: Content on the right (on daisyui "end") side of a timeline.
7
7
  # We chose not to use start/end because of the keywork conflict with ruby.
8
8
 
9
- def view_template(&block)
10
- div(**attrs, &block)
9
+ def view_template(&)
10
+ div(**attrs, &)
11
11
  end
12
12
 
13
13
  private
@@ -7,25 +7,17 @@ module Protos
7
7
 
8
8
  option :vertical, type: Types::Bool, default: -> { false }
9
9
 
10
- def view_template(&block)
11
- ul(**attrs, &block)
10
+ def view_template(&)
11
+ ul(**attrs, &)
12
12
  end
13
13
 
14
- def item(...)
15
- Item.new(...)
16
- end
14
+ def item(...) = render Item.new(...)
17
15
 
18
- def left(...)
19
- Left.new(...)
20
- end
16
+ def left(...) = render Left.new(...)
21
17
 
22
- def center(...)
23
- Center.new(...)
24
- end
18
+ def center(...) = render Center.new(...)
25
19
 
26
- def right(...)
27
- Right.new(...)
28
- end
20
+ def right(...) = render Right.new(...)
29
21
 
30
22
  private
31
23
 
@@ -10,6 +10,7 @@ module Protos
10
10
  button(
11
11
  autofocus: true,
12
12
  formmethod: :dialog,
13
+ formnovalidate: true,
13
14
  **attrs,
14
15
  &block
15
16
  )
data/lib/protos/toast.rb CHANGED
@@ -23,13 +23,11 @@ module Protos
23
23
  default: -> { :bottom_end },
24
24
  reader: false
25
25
 
26
- def view_template(&block)
27
- dialog(**attrs, &block)
26
+ def view_template(&)
27
+ dialog(**attrs, &)
28
28
  end
29
29
 
30
- def close_button(...)
31
- CloseButton.new(...)
32
- end
30
+ def close_button(...) = render CloseButton.new(...)
33
31
 
34
32
  private
35
33
 
@@ -3,19 +3,7 @@
3
3
  module Protos
4
4
  class TokenList
5
5
  # DOCS: A list of utility tokens that can handle parsing and merging sets of
6
- # tokens together safely. It uses TailwindMerge to merge the tokens together
7
- # while accounting for their conflicts.
8
-
9
- def self.parse(input)
10
- case input
11
- when String then new(input.split)
12
- when Array then new(input)
13
- when TokenList then input
14
- when NilClass then new
15
- else raise ArgumentError,
16
- "Invalid input for #{self.class.name}: #{input.inspect}"
17
- end
18
- end
6
+ # tokens together safely.
19
7
 
20
8
  attr_reader :tokens
21
9
 
@@ -23,34 +11,33 @@ module Protos
23
11
  @tokens = Set.new(tokens)
24
12
  end
25
13
 
14
+ def empty?
15
+ @tokens.empty?
16
+ end
17
+
26
18
  def to_s
27
19
  @tokens.join(" ")
28
20
  end
29
21
 
30
- def -(other)
31
- other = TokenList.parse(other)
32
- self.class.new(@tokens - other.tokens)
22
+ def remove(tokens)
23
+ @tokens.subtract(parse(tokens))
24
+ self
33
25
  end
34
26
 
35
- def +(other)
36
- other = TokenList.parse(other)
37
- self.class.new(@tokens + other.tokens)
27
+ def add(tokens)
28
+ @tokens.merge(parse(tokens))
29
+ self
38
30
  end
39
31
 
40
- def remove(token)
41
- tap do
42
- self.class.parse(token).tokens.each do |token|
43
- @tokens.delete(token)
44
- end
45
- end
32
+ def clear
33
+ @tokens.clear
34
+ self
46
35
  end
47
36
 
48
- def add(input)
49
- tap do
50
- self.class.parse(input).tokens.each do |token|
51
- @tokens.add(token)
52
- end
53
- end
37
+ private
38
+
39
+ def parse(tokens)
40
+ tokens.split
54
41
  end
55
42
  end
56
43
  end
@@ -12,8 +12,8 @@ module Protos
12
12
  option :size, type: SizeTypes, default: -> { "md" }, reader: false
13
13
  option :level, type: LevelTypes, default: -> { 1 }, reader: false
14
14
 
15
- def view_template(&block)
16
- send(element, **attrs, &block)
15
+ def view_template(&)
16
+ send(element, **attrs, &)
17
17
  end
18
18
 
19
19
  private
@@ -5,8 +5,8 @@ module Protos
5
5
  class InlineLink < Component
6
6
  # DOCS: A link that is styled to be inline with text
7
7
 
8
- def view_template(&block)
9
- a(**attrs, &block)
8
+ def view_template(&)
9
+ a(**attrs, &)
10
10
  end
11
11
 
12
12
  private
@@ -14,7 +14,7 @@ module Protos
14
14
  def theme
15
15
  {
16
16
  container: tokens(
17
- "font-medium",
17
+ "font-semibold",
18
18
  "hover:underline",
19
19
  "underline-offset-4",
20
20
  "cursor-pointer"
@@ -5,8 +5,8 @@ module Protos
5
5
  class Paragraph < Component
6
6
  # DOCS: A paragraph of text
7
7
 
8
- def view_template(&block)
9
- p(**attrs, &block)
8
+ def view_template(&)
9
+ p(**attrs, &)
10
10
  end
11
11
 
12
12
  private
@@ -5,28 +5,28 @@ module Protos
5
5
  # DOCS: The core typography module that can be mixedin to override the
6
6
  # default elements with custom elements.
7
7
 
8
- def h1(**options, &block)
9
- render(Heading.new(level: 1, size: :xl, **options), &block)
8
+ def h1(**, &)
9
+ render Heading.new(level: 1, size: :xl, **, &)
10
10
  end
11
11
 
12
- def h2(**options, &block)
13
- render(Heading.new(level: 2, size: :lg, **options), &block)
12
+ def h2(**, &)
13
+ render Heading.new(level: 2, size: :lg, **, &)
14
14
  end
15
15
 
16
- def h3(**options, &block)
17
- render(Heading.new(level: 3, size: :md, **options), &block)
16
+ def h3(**, &)
17
+ render Heading.new(level: 3, size: :md, **, &)
18
18
  end
19
19
 
20
- def h4(**options, &block)
21
- render(Heading.new(level: 4, size: :sm, **options), &block)
20
+ def h4(**, &)
21
+ render Heading.new(level: 4, size: :sm, **, &)
22
22
  end
23
23
 
24
- def p(**options, &block)
25
- render(Paragraph.new(**options), &block)
24
+ def p(**, &)
25
+ render Paragraph.new(**, &)
26
26
  end
27
27
 
28
- def inline_a(**options, &block)
29
- render(InlineLink.new(**options), &block)
28
+ def inline_a(**, &)
29
+ render InlineLink.new(**, &)
30
30
  end
31
31
  end
32
32
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Protos
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.1"
5
5
  end
data/protos.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = "A UI component library built with phlex and daisyui"
13
13
  spec.homepage = "https://github.com/inhouse-work/protos"
14
14
  spec.license = "MIT"
15
- spec.required_ruby_version = ">= 3.1"
15
+ spec.required_ruby_version = ">= 3.2"
16
16
  spec.requirements << "tailwindcss"
17
17
  spec.requirements << "daisyui"
18
18
  spec.requirements << "protos-stimulus"
@@ -26,7 +26,19 @@ Gem::Specification.new do |spec|
26
26
  spec.files = Dir.chdir(__dir__) do
27
27
  `git ls-files -z`.split("\x0").reject do |f|
28
28
  (File.expand_path(f) == __FILE__) ||
29
- f.start_with?(*%w[bin/ test/ spec/ features/ .git appveyor Gemfile])
29
+ f.start_with?(
30
+ *%w[
31
+ bin/
32
+ test/
33
+ spec/
34
+ features/
35
+ rakelib/
36
+ benchmark/
37
+ .git
38
+ appveyor
39
+ Gemfile
40
+ ]
41
+ )
30
42
  end
31
43
  end
32
44
  spec.bindir = "exe"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protos
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nolan J Tait
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-07 00:00:00.000000000 Z
11
+ date: 2024-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-core
@@ -93,6 +93,8 @@ files:
93
93
  - LICENSE.txt
94
94
  - README.md
95
95
  - Rakefile
96
+ - benchmarks/.keep
97
+ - benchmarks/table.txt
96
98
  - examples/list.rb
97
99
  - examples/navbar.rb
98
100
  - lib/protos.rb
@@ -205,7 +207,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
205
207
  requirements:
206
208
  - - ">="
207
209
  - !ruby/object:Gem::Version
208
- version: '3.1'
210
+ version: '3.2'
209
211
  required_rubygems_version: !ruby/object:Gem::Requirement
210
212
  requirements:
211
213
  - - ">="
@@ -215,7 +217,7 @@ requirements:
215
217
  - tailwindcss
216
218
  - daisyui
217
219
  - protos-stimulus
218
- rubygems_version: 3.5.3
220
+ rubygems_version: 3.5.7
219
221
  signing_key:
220
222
  specification_version: 4
221
223
  summary: A UI component library built with phlex and daisyui