protos 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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 +34 -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,44 @@ 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
+ @theme[key].add(value)
39
44
  end
40
45
 
41
46
  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
47
+ @theme[key].remove(value)
48
+ @theme.delete(key) if @theme[key].empty?
49
49
  end
50
50
 
51
51
  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
52
+ @theme[key].clear.add(value)
62
53
  end
63
54
 
64
55
  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
56
+ return self unless hash
57
+
58
+ hash.each do |key, value|
59
+ if key?(key)
60
+ add(key, value)
61
+ elsif negation?(key)
62
+ remove(key[1..].to_sym, value)
63
+ elsif override?(key)
64
+ set(key[..-2].to_sym, value)
65
+ else
66
+ set(key, value)
80
67
  end
81
68
  end
69
+
70
+ self
82
71
  end
83
72
 
84
73
  private
85
74
 
86
75
  def negation?(key)
87
- key.to_s.start_with?("!")
76
+ key.start_with?("!")
88
77
  end
89
78
 
90
79
  def override?(key)
91
- key.to_s.end_with?("!")
80
+ key.end_with?("!")
92
81
  end
93
82
  end
94
83
  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.0"
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.0
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