protos 0.1.0
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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +12 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +150 -0
- data/Rakefile +12 -0
- data/examples/navbar.rb +43 -0
- data/lib/protos/accordion/item.rb +33 -0
- data/lib/protos/accordion.rb +34 -0
- data/lib/protos/alert/actions.rb +19 -0
- data/lib/protos/alert/icon.rb +19 -0
- data/lib/protos/alert.rb +46 -0
- data/lib/protos/attributes.rb +42 -0
- data/lib/protos/avatar.rb +71 -0
- data/lib/protos/card/actions.rb +19 -0
- data/lib/protos/card/body.rb +19 -0
- data/lib/protos/card/image.rb +11 -0
- data/lib/protos/card/title.rb +19 -0
- data/lib/protos/card.rb +55 -0
- data/lib/protos/collapse/content.rb +19 -0
- data/lib/protos/collapse/title.rb +19 -0
- data/lib/protos/collapse.rb +31 -0
- data/lib/protos/combobox.rb +53 -0
- data/lib/protos/command/dialog.rb +32 -0
- data/lib/protos/command/empty.rb +25 -0
- data/lib/protos/command/group.rb +13 -0
- data/lib/protos/command/input.rb +44 -0
- data/lib/protos/command/item.rb +19 -0
- data/lib/protos/command/list.rb +19 -0
- data/lib/protos/command/title.rb +19 -0
- data/lib/protos/command/trigger.rb +19 -0
- data/lib/protos/command.rb +49 -0
- data/lib/protos/component.rb +79 -0
- data/lib/protos/drawer/content.rb +19 -0
- data/lib/protos/drawer/side.rb +25 -0
- data/lib/protos/drawer/trigger.rb +21 -0
- data/lib/protos/drawer.rb +35 -0
- data/lib/protos/dropdown/item.rb +11 -0
- data/lib/protos/dropdown/menu.rb +25 -0
- data/lib/protos/dropdown/trigger.rb +11 -0
- data/lib/protos/dropdown.rb +59 -0
- data/lib/protos/engine.rb +7 -0
- data/lib/protos/list/item.rb +22 -0
- data/lib/protos/list.rb +30 -0
- data/lib/protos/modal/close_button.rb +16 -0
- data/lib/protos/modal/dialog.rb +30 -0
- data/lib/protos/modal/trigger.rb +19 -0
- data/lib/protos/modal.rb +31 -0
- data/lib/protos/popover/content.rb +19 -0
- data/lib/protos/popover/trigger.rb +11 -0
- data/lib/protos/popover.rb +54 -0
- data/lib/protos/table/body.rb +11 -0
- data/lib/protos/table/caption.rb +19 -0
- data/lib/protos/table/cell.rb +11 -0
- data/lib/protos/table/footer.rb +11 -0
- data/lib/protos/table/head.rb +11 -0
- data/lib/protos/table/header.rb +11 -0
- data/lib/protos/table/row.rb +11 -0
- data/lib/protos/table.rb +48 -0
- data/lib/protos/theme.rb +76 -0
- data/lib/protos/timeline/center.rb +19 -0
- data/lib/protos/timeline/item.rb +11 -0
- data/lib/protos/timeline/left.rb +19 -0
- data/lib/protos/timeline/right.rb +19 -0
- data/lib/protos/timeline.rb +38 -0
- data/lib/protos/token_list.rb +41 -0
- data/lib/protos/types.rb +32 -0
- data/lib/protos/typography/heading.rb +44 -0
- data/lib/protos/typography/inline_link.rb +24 -0
- data/lib/protos/typography/paragraph.rb +22 -0
- data/lib/protos/typography.rb +29 -0
- data/lib/protos/version.rb +5 -0
- data/lib/protos.rb +94 -0
- data/protos.gemspec +45 -0
- metadata +180 -0
data/lib/protos/list.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class List < Component
|
5
|
+
option :ordered, Types::Bool, default: -> { false }, reader: false
|
6
|
+
|
7
|
+
def template(&block)
|
8
|
+
send(element, **attrs, &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def item(...)
|
12
|
+
Item.new(...)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def css
|
18
|
+
{
|
19
|
+
container: tokens(
|
20
|
+
"join",
|
21
|
+
"join-vertical"
|
22
|
+
)
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def element
|
27
|
+
@ordered ? :ol : :ul
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Modal
|
5
|
+
class Dialog < Component
|
6
|
+
def template(&block)
|
7
|
+
dialog(**attrs) do
|
8
|
+
div(class: css[:modal], &block)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def theme
|
15
|
+
{
|
16
|
+
container: tokens("modal", "modal-bottom", "sm:modal-middle"),
|
17
|
+
modal: tokens("modal-box", "flex", "flex-col", "gap-xs")
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def attrs
|
22
|
+
@attrs ||= build_attrs(
|
23
|
+
{
|
24
|
+
data: { "protos--modal-target": "modal" }
|
25
|
+
}
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Modal
|
5
|
+
class Trigger < Component
|
6
|
+
def template(&block)
|
7
|
+
button(**attrs, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def default_attrs
|
13
|
+
{
|
14
|
+
data: { action: "protos--modal#open" }
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/protos/modal.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Modal < Protos::Component
|
5
|
+
def template(&block)
|
6
|
+
div(**attrs, class: css[:container], &block)
|
7
|
+
end
|
8
|
+
|
9
|
+
def close_button(...)
|
10
|
+
CloseButton.new(...)
|
11
|
+
end
|
12
|
+
|
13
|
+
def dialog(...)
|
14
|
+
Dialog.new(...)
|
15
|
+
end
|
16
|
+
|
17
|
+
def trigger(...)
|
18
|
+
Trigger.new(...)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def default_attrs
|
24
|
+
{
|
25
|
+
data: {
|
26
|
+
controller: "protos--modal"
|
27
|
+
}
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Popover
|
5
|
+
class Content < Component
|
6
|
+
def template(&block)
|
7
|
+
div(**attrs, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def theme
|
13
|
+
{
|
14
|
+
container: tokens("dropdown-content", "z-10")
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Popover < Component
|
5
|
+
# DOCS: Like a dropdown, but instead of a list of menu items, its just
|
6
|
+
# a rendered block
|
7
|
+
|
8
|
+
PositionTypes = Types::Coercible::Symbol.enum(
|
9
|
+
:top,
|
10
|
+
:bottom,
|
11
|
+
:left,
|
12
|
+
:right,
|
13
|
+
:start,
|
14
|
+
:end
|
15
|
+
)
|
16
|
+
|
17
|
+
option :position,
|
18
|
+
type: PositionTypes,
|
19
|
+
default: -> { :bottom },
|
20
|
+
reader: false
|
21
|
+
option :hover, type: Types::Bool, default: -> { false }
|
22
|
+
|
23
|
+
def template(&block)
|
24
|
+
details(**attrs, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def content(...)
|
28
|
+
Content.new(...)
|
29
|
+
end
|
30
|
+
|
31
|
+
def trigger(...)
|
32
|
+
Trigger.new(...)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def position
|
38
|
+
{
|
39
|
+
bottom: "dropdown-bottom",
|
40
|
+
top: "dropdown-top",
|
41
|
+
left: "dropdown-left",
|
42
|
+
right: "dropdown-right",
|
43
|
+
end: "dropdown-end",
|
44
|
+
start: "dropdown-start"
|
45
|
+
}.fetch(@position)
|
46
|
+
end
|
47
|
+
|
48
|
+
def theme
|
49
|
+
{
|
50
|
+
container: tokens("dropdown", position)
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Table
|
5
|
+
class Caption < Component
|
6
|
+
def template(&block)
|
7
|
+
caption(**attrs, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def theme
|
13
|
+
{
|
14
|
+
container: tokens("caption-bottom", "p-sm")
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/protos/table.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Table < Component
|
5
|
+
def template(&block)
|
6
|
+
div(**attrs) do
|
7
|
+
table(class: css[:table], &block)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def body(...)
|
12
|
+
Body.new(...)
|
13
|
+
end
|
14
|
+
|
15
|
+
def caption(...)
|
16
|
+
Caption.new(...)
|
17
|
+
end
|
18
|
+
|
19
|
+
def cell(...)
|
20
|
+
Cell.new(...)
|
21
|
+
end
|
22
|
+
|
23
|
+
def footer(...)
|
24
|
+
Footer.new(...)
|
25
|
+
end
|
26
|
+
|
27
|
+
def head(...)
|
28
|
+
Head.new(...)
|
29
|
+
end
|
30
|
+
|
31
|
+
def header(...)
|
32
|
+
Header.new(...)
|
33
|
+
end
|
34
|
+
|
35
|
+
def row(...)
|
36
|
+
Row.new(...)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def theme
|
42
|
+
{
|
43
|
+
container: tokens("w-full", "overflow-x-auto"),
|
44
|
+
table: tokens("table")
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/protos/theme.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Theme
|
5
|
+
def initialize(theme = {}, **kwargs)
|
6
|
+
@theme = theme.merge(kwargs)
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](key)
|
10
|
+
@theme[key]
|
11
|
+
end
|
12
|
+
|
13
|
+
def key?(key)
|
14
|
+
@theme.key?(key)
|
15
|
+
end
|
16
|
+
|
17
|
+
def add(key, value)
|
18
|
+
current_tokens = parse(@theme.fetch(key, ""))
|
19
|
+
new_tokens = parse(value)
|
20
|
+
tokens = current_tokens + new_tokens
|
21
|
+
|
22
|
+
@theme[key] = tokens.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
def remove(key, value)
|
26
|
+
current_tokens = parse(@theme.fetch(key, ""))
|
27
|
+
removable_tokens = parse(value)
|
28
|
+
tokens = current_tokens - removable_tokens
|
29
|
+
|
30
|
+
@theme[key] = tokens.to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
def set(key, value)
|
34
|
+
if value.is_a?(Hash)
|
35
|
+
@theme[key] = value
|
36
|
+
else
|
37
|
+
tokens = parse(value)
|
38
|
+
@theme[key] = tokens.to_s
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def merge(hash)
|
43
|
+
hash ||= {}
|
44
|
+
|
45
|
+
tap do
|
46
|
+
hash.each_key do |key|
|
47
|
+
if key?(key)
|
48
|
+
add(key, hash[key])
|
49
|
+
elsif negation?(key)
|
50
|
+
no_bang = key.to_s[1..].to_sym
|
51
|
+
remove(no_bang, hash[key])
|
52
|
+
elsif override?(key)
|
53
|
+
no_bang = key.to_s.chomp("!").to_sym
|
54
|
+
set(no_bang, hash[key])
|
55
|
+
else
|
56
|
+
set(key, hash[key])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def parse(value)
|
65
|
+
TokenList.parse(value)
|
66
|
+
end
|
67
|
+
|
68
|
+
def negation?(key)
|
69
|
+
key.to_s.start_with?("!")
|
70
|
+
end
|
71
|
+
|
72
|
+
def override?(key)
|
73
|
+
key.to_s.end_with?("!")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Timeline
|
5
|
+
class Center < Component
|
6
|
+
def template(&block)
|
7
|
+
div(**attrs, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def theme
|
13
|
+
{
|
14
|
+
container: tokens("timeline-middle")
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Timeline
|
5
|
+
class Left < Component
|
6
|
+
def template(&block)
|
7
|
+
div(**attrs, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def theme
|
13
|
+
{
|
14
|
+
container: tokens("timeline-start")
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Timeline
|
5
|
+
class Right < Component
|
6
|
+
def template(&block)
|
7
|
+
div(**attrs, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def theme
|
13
|
+
{
|
14
|
+
container: tokens("timeline-end")
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Timeline < Component
|
5
|
+
option :vertical, type: Types::Bool, default: -> { false }
|
6
|
+
|
7
|
+
def template(&block)
|
8
|
+
ul(**attrs, &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def item(...)
|
12
|
+
Item.new(...)
|
13
|
+
end
|
14
|
+
|
15
|
+
def left(...)
|
16
|
+
Left.new(...)
|
17
|
+
end
|
18
|
+
|
19
|
+
def center(...)
|
20
|
+
Center.new(...)
|
21
|
+
end
|
22
|
+
|
23
|
+
def right(...)
|
24
|
+
Right.new(...)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def css
|
30
|
+
{
|
31
|
+
container: tokens(
|
32
|
+
"timeline",
|
33
|
+
vertical: "timeline-vertical"
|
34
|
+
)
|
35
|
+
}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class TokenList
|
5
|
+
def self.parse(input)
|
6
|
+
case input
|
7
|
+
when String then new(input.split)
|
8
|
+
when Array then new(input)
|
9
|
+
else raise ArgumentError, "Invalid input: #{input.inspect}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :tokens
|
14
|
+
|
15
|
+
def initialize(tokens)
|
16
|
+
@tokens = Set.new(tokens)
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
@tokens.to_a.join(" ")
|
21
|
+
end
|
22
|
+
|
23
|
+
def -(other)
|
24
|
+
other = TokenList.parse(other) unless other.is_a?(TokenList)
|
25
|
+
self.class.new(@tokens - other.tokens)
|
26
|
+
end
|
27
|
+
|
28
|
+
def +(other)
|
29
|
+
other = TokenList.parse(other) unless other.is_a?(TokenList)
|
30
|
+
self.class.new(@tokens + other.tokens)
|
31
|
+
end
|
32
|
+
|
33
|
+
def remove(token)
|
34
|
+
@tokens.delete(token)
|
35
|
+
end
|
36
|
+
|
37
|
+
def add(token)
|
38
|
+
@tokens.add(token)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/protos/types.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
module Types
|
5
|
+
include Dry.Types()
|
6
|
+
|
7
|
+
MaskShapes = Types::Coercible::Symbol.enum(
|
8
|
+
:none,
|
9
|
+
:squircle,
|
10
|
+
:heart,
|
11
|
+
:hexagon,
|
12
|
+
:hexagon2,
|
13
|
+
:decagon,
|
14
|
+
:pentagon,
|
15
|
+
:diamond,
|
16
|
+
:square,
|
17
|
+
:circle,
|
18
|
+
:parallelogram,
|
19
|
+
:parallelogram2,
|
20
|
+
:parallelogram3,
|
21
|
+
:parallelogram4,
|
22
|
+
:star,
|
23
|
+
:star2,
|
24
|
+
:triangle,
|
25
|
+
:triangle2,
|
26
|
+
:triangle3,
|
27
|
+
:triangle4,
|
28
|
+
:half1,
|
29
|
+
:half2
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
module Typography
|
5
|
+
class Heading < Protos::Component
|
6
|
+
SizeTypes = Types::Coercible::Symbol.enum(:xs, :sm, :md, :lg, :xl)
|
7
|
+
LevelTypes = Types::Integer.enum(1, 2, 3, 4, 5, 6)
|
8
|
+
|
9
|
+
option :size, type: SizeTypes, default: -> { "md" }, reader: false
|
10
|
+
option :level, type: LevelTypes, default: -> { 1 }, reader: false
|
11
|
+
|
12
|
+
def template(&block)
|
13
|
+
send(element, **attrs, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def theme
|
19
|
+
{
|
20
|
+
container: tokens(
|
21
|
+
size,
|
22
|
+
"scroll-m-20",
|
23
|
+
"tracking-tight",
|
24
|
+
"transition-colors"
|
25
|
+
)
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def size
|
30
|
+
{
|
31
|
+
xs: "text-lg font-medium",
|
32
|
+
sm: "text-xl font-medium",
|
33
|
+
md: "text-2xl font-semibold",
|
34
|
+
lg: "text-3xl font-semibold md:text-4xl",
|
35
|
+
xl: "text-4xl font-bold md:text-5xl"
|
36
|
+
}.fetch(@size.to_sym)
|
37
|
+
end
|
38
|
+
|
39
|
+
def element
|
40
|
+
%i[h1 h2 h3 h4 h5 h6][@level - 1]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
module Typography
|
5
|
+
class InlineLink < Component
|
6
|
+
def template(&block)
|
7
|
+
a(**attrs, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def theme
|
13
|
+
{
|
14
|
+
container: tokens(
|
15
|
+
"font-medium",
|
16
|
+
"hover:underline",
|
17
|
+
"underline-offset-4",
|
18
|
+
"cursor-pointer"
|
19
|
+
)
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|