protos 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Collapse
|
5
|
+
class Title < Component
|
6
|
+
def template(&block)
|
7
|
+
div(**attrs, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def theme
|
13
|
+
{
|
14
|
+
container: tokens("collapse-title")
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Collapse < Component
|
5
|
+
def template(&block)
|
6
|
+
div(**attrs, &block)
|
7
|
+
end
|
8
|
+
|
9
|
+
def title(...)
|
10
|
+
Title.new(...)
|
11
|
+
end
|
12
|
+
|
13
|
+
def content(...)
|
14
|
+
Content.new(...)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def theme
|
20
|
+
{
|
21
|
+
container: tokens("collapse", "collapse-arrow", "bg-base-100")
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
def default_attrs
|
26
|
+
{
|
27
|
+
tabindex: 0
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Combobox < Component
|
5
|
+
def template
|
6
|
+
div(**attrs) do
|
7
|
+
render Popover.new do
|
8
|
+
yield if block_given?
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def trigger(...)
|
14
|
+
Popover::Trigger.new(...)
|
15
|
+
end
|
16
|
+
|
17
|
+
def content(...)
|
18
|
+
Popover::Content.new(...)
|
19
|
+
end
|
20
|
+
|
21
|
+
def input(...)
|
22
|
+
Command::Input.new(...)
|
23
|
+
end
|
24
|
+
|
25
|
+
def group(...)
|
26
|
+
Command::Group.new(...)
|
27
|
+
end
|
28
|
+
|
29
|
+
def item(...)
|
30
|
+
Command::Item.new(...)
|
31
|
+
end
|
32
|
+
|
33
|
+
def list(...)
|
34
|
+
Command::List.new(...)
|
35
|
+
end
|
36
|
+
|
37
|
+
def title(...)
|
38
|
+
Command::Title.new(...)
|
39
|
+
end
|
40
|
+
|
41
|
+
def empty(...)
|
42
|
+
Command::Empty.new(...)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def default_attrs
|
48
|
+
{
|
49
|
+
data: { controller: "protos--command" }
|
50
|
+
}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Command
|
5
|
+
class Dialog < Component
|
6
|
+
def template(&block)
|
7
|
+
dialog(**attrs) do
|
8
|
+
div(class: css[:modal], &block)
|
9
|
+
form(method: :dialog, class: css[:form]) do
|
10
|
+
button { "close" }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def default_attrs
|
18
|
+
{
|
19
|
+
data: { "protos--modal-target": "modal" }
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def theme
|
24
|
+
{
|
25
|
+
container: tokens("modal", "modal-bottom", "sm:modal-middle"),
|
26
|
+
modal: tokens("modal-box", "p-0"),
|
27
|
+
form: tokens("modal-backdrop")
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Command
|
5
|
+
class Empty < Component
|
6
|
+
def template(&block)
|
7
|
+
li(**attrs, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def default_attrs
|
13
|
+
{
|
14
|
+
data: { "protos--command-target": "empty" }
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def theme
|
19
|
+
{
|
20
|
+
container: tokens("hidden", "px-xs", "py-sm")
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Command
|
5
|
+
class Input < Component
|
6
|
+
option :placeholder,
|
7
|
+
default: -> {
|
8
|
+
"Type a command or search..."
|
9
|
+
},
|
10
|
+
reader: :private
|
11
|
+
|
12
|
+
def template(&block)
|
13
|
+
div(**attrs) do
|
14
|
+
label(class: css[:label]) do
|
15
|
+
div(class: css[:icon], &block) if block
|
16
|
+
input(
|
17
|
+
type: :text,
|
18
|
+
data: { action: "protos--command#filter" },
|
19
|
+
class: css[:input],
|
20
|
+
placeholder:
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def theme
|
29
|
+
{
|
30
|
+
container: tokens("form-control"),
|
31
|
+
label: tokens(
|
32
|
+
"input",
|
33
|
+
"input-bordered",
|
34
|
+
"flex",
|
35
|
+
"items-center",
|
36
|
+
"gap-2"
|
37
|
+
),
|
38
|
+
input: tokens("grow", "bg-transparent"),
|
39
|
+
icon: tokens("flex", "place-items-center")
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Command
|
5
|
+
class Item < Component
|
6
|
+
def template(&block)
|
7
|
+
li(**attrs, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def default_attrs
|
13
|
+
{
|
14
|
+
data: { "protos--command-target": "item" }
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Command
|
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
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Command < Component
|
5
|
+
def template(&block)
|
6
|
+
div(**attrs, &block)
|
7
|
+
end
|
8
|
+
|
9
|
+
def input(...)
|
10
|
+
Input.new(...)
|
11
|
+
end
|
12
|
+
|
13
|
+
def list(...)
|
14
|
+
List.new(...)
|
15
|
+
end
|
16
|
+
|
17
|
+
def trigger(...)
|
18
|
+
Trigger.new(...)
|
19
|
+
end
|
20
|
+
|
21
|
+
def dialog(...)
|
22
|
+
Dialog.new(...)
|
23
|
+
end
|
24
|
+
|
25
|
+
def title(...)
|
26
|
+
Title.new(...)
|
27
|
+
end
|
28
|
+
|
29
|
+
def group(...)
|
30
|
+
Group.new(...)
|
31
|
+
end
|
32
|
+
|
33
|
+
def item(...)
|
34
|
+
Item.new
|
35
|
+
end
|
36
|
+
|
37
|
+
def empty(...)
|
38
|
+
Empty.new(...)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def default_attrs
|
44
|
+
{
|
45
|
+
data: { controller: "protos--command protos--modal" }
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Component < Phlex::HTML
|
5
|
+
# DOCS: Base component
|
6
|
+
|
7
|
+
extend Dry::Initializer
|
8
|
+
extend Dry::Core::ClassAttributes
|
9
|
+
|
10
|
+
# Define methods for css and attrs. Each is expected to return a hash
|
11
|
+
defines :css_method, type: Types::Symbol
|
12
|
+
defines :attrs_method, type: Types::Symbol
|
13
|
+
|
14
|
+
css_method :theme
|
15
|
+
attrs_method :default_attrs
|
16
|
+
|
17
|
+
# Theme can override the css hash and add additional styles
|
18
|
+
option :theme, as: :theme_override, default: -> { {} }, reader: :private
|
19
|
+
# Class becomes the :container key in the css hash
|
20
|
+
option :class, as: :container_class, default: -> { "" }, reader: :private
|
21
|
+
option :html_options, default: -> { {} }, reader: :private
|
22
|
+
|
23
|
+
# Adds non-defined options to the html_options hash
|
24
|
+
def initialize(*args, **kwargs, &block)
|
25
|
+
raise_block_in_initializer_error if block
|
26
|
+
|
27
|
+
defined_keys = self.class.dry_initializer.definitions.keys
|
28
|
+
defined, undefined =
|
29
|
+
kwargs
|
30
|
+
.partition { |key, _| defined_keys.include?(key) }
|
31
|
+
.map(&:to_h)
|
32
|
+
|
33
|
+
super(*args, html_options: undefined, **defined)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def raise_block_in_initializer_error
|
39
|
+
raise(
|
40
|
+
ArgumentError,
|
41
|
+
"It is unexpected to pass a block to the initializer of a component. " \
|
42
|
+
"You might have tried to render and passed a block but it went to " \
|
43
|
+
"the component.new. Check your render call."
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
def attrs
|
48
|
+
@attrs ||= build_attrs
|
49
|
+
end
|
50
|
+
|
51
|
+
def css
|
52
|
+
@css ||= build_theme
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_attrs(...)
|
56
|
+
defaults = if respond_to?(self.class.attrs_method, :include_private)
|
57
|
+
send(self.class.attrs_method)
|
58
|
+
end
|
59
|
+
|
60
|
+
Attributes
|
61
|
+
.new(...)
|
62
|
+
.merge(defaults)
|
63
|
+
.merge(html_options)
|
64
|
+
.merge(class: css[:container])
|
65
|
+
end
|
66
|
+
|
67
|
+
def build_theme(...)
|
68
|
+
component_style = if respond_to?(self.class.css_method, :include_private)
|
69
|
+
send(self.class.css_method)
|
70
|
+
end
|
71
|
+
|
72
|
+
Theme
|
73
|
+
.new(...)
|
74
|
+
.merge(component_style)
|
75
|
+
.merge(theme_override)
|
76
|
+
.merge(container: container_class)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Drawer
|
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("drawer-content")
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Drawer
|
5
|
+
class Side < Component
|
6
|
+
option :id, type: Types::Coercible::String
|
7
|
+
|
8
|
+
def template
|
9
|
+
aside(**attrs) do
|
10
|
+
label(for: id, aria_label: "close sidebar", class: css[:toggle])
|
11
|
+
yield if block_given?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def theme
|
18
|
+
{
|
19
|
+
container: tokens("drawer-side", "z-20"),
|
20
|
+
toggle: tokens("drawer-overlay")
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Drawer
|
5
|
+
class Trigger < Component
|
6
|
+
option :id, type: Types::Coercible::String
|
7
|
+
|
8
|
+
def template(&block)
|
9
|
+
label(for: id, **attrs, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def theme
|
15
|
+
{
|
16
|
+
container: tokens("drawer-button")
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Drawer < Component
|
5
|
+
option :id, type: Types::Coercible::String
|
6
|
+
|
7
|
+
def template
|
8
|
+
div(**attrs) do
|
9
|
+
input(id:, type: :checkbox, class: css[:toggle])
|
10
|
+
yield if block_given?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def content(...)
|
15
|
+
Content.new(...)
|
16
|
+
end
|
17
|
+
|
18
|
+
def side(*args, **kwargs, &block)
|
19
|
+
Side.new(*args, id:, **kwargs, &block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def trigger(*args, **kwargs, &block)
|
23
|
+
Trigger.new(*args, id:, **kwargs, &block)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def theme
|
29
|
+
{
|
30
|
+
container: tokens("drawer"),
|
31
|
+
toggle: tokens("drawer-toggle")
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Dropdown
|
5
|
+
class Menu < Component
|
6
|
+
def template(&block)
|
7
|
+
ul(**attrs, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def theme
|
13
|
+
{
|
14
|
+
container: tokens(
|
15
|
+
"menu",
|
16
|
+
"dropdown-content",
|
17
|
+
"z-10",
|
18
|
+
"bg-base-100",
|
19
|
+
"rounded-box"
|
20
|
+
)
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class Dropdown < Component
|
5
|
+
PositionTypes = Types::Coercible::Symbol.enum(
|
6
|
+
:top,
|
7
|
+
:bottom,
|
8
|
+
:left,
|
9
|
+
:right,
|
10
|
+
:start,
|
11
|
+
:end
|
12
|
+
)
|
13
|
+
|
14
|
+
option :position,
|
15
|
+
type: PositionTypes,
|
16
|
+
default: -> { :bottom },
|
17
|
+
reader: false
|
18
|
+
option :hover, type: Types::Bool, default: -> { false }
|
19
|
+
|
20
|
+
def template(&block)
|
21
|
+
details(**attrs, &block)
|
22
|
+
end
|
23
|
+
|
24
|
+
def item(...)
|
25
|
+
Item.new(...)
|
26
|
+
end
|
27
|
+
|
28
|
+
def menu(...)
|
29
|
+
Menu.new(...)
|
30
|
+
end
|
31
|
+
|
32
|
+
def trigger(...)
|
33
|
+
Trigger.new(...)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def position
|
39
|
+
{
|
40
|
+
bottom: "dropdown-bottom",
|
41
|
+
top: "dropdown-top",
|
42
|
+
left: "dropdown-left",
|
43
|
+
right: "dropdown-right",
|
44
|
+
end: "dropdown-end",
|
45
|
+
start: "dropdown-start"
|
46
|
+
}.fetch(@position)
|
47
|
+
end
|
48
|
+
|
49
|
+
def theme
|
50
|
+
{
|
51
|
+
container: tokens(
|
52
|
+
"dropdown",
|
53
|
+
position,
|
54
|
+
hover: "dropdown-hover"
|
55
|
+
)
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Protos
|
4
|
+
class List
|
5
|
+
class Item < Component
|
6
|
+
def template(&block)
|
7
|
+
li(**attrs, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def theme
|
13
|
+
{
|
14
|
+
container: tokens(
|
15
|
+
"join-item",
|
16
|
+
"[&:not(:first-child)]:border-t-0"
|
17
|
+
)
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|