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.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +12 -0
  4. data/CHANGELOG.md +5 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +150 -0
  7. data/Rakefile +12 -0
  8. data/examples/navbar.rb +43 -0
  9. data/lib/protos/accordion/item.rb +33 -0
  10. data/lib/protos/accordion.rb +34 -0
  11. data/lib/protos/alert/actions.rb +19 -0
  12. data/lib/protos/alert/icon.rb +19 -0
  13. data/lib/protos/alert.rb +46 -0
  14. data/lib/protos/attributes.rb +42 -0
  15. data/lib/protos/avatar.rb +71 -0
  16. data/lib/protos/card/actions.rb +19 -0
  17. data/lib/protos/card/body.rb +19 -0
  18. data/lib/protos/card/image.rb +11 -0
  19. data/lib/protos/card/title.rb +19 -0
  20. data/lib/protos/card.rb +55 -0
  21. data/lib/protos/collapse/content.rb +19 -0
  22. data/lib/protos/collapse/title.rb +19 -0
  23. data/lib/protos/collapse.rb +31 -0
  24. data/lib/protos/combobox.rb +53 -0
  25. data/lib/protos/command/dialog.rb +32 -0
  26. data/lib/protos/command/empty.rb +25 -0
  27. data/lib/protos/command/group.rb +13 -0
  28. data/lib/protos/command/input.rb +44 -0
  29. data/lib/protos/command/item.rb +19 -0
  30. data/lib/protos/command/list.rb +19 -0
  31. data/lib/protos/command/title.rb +19 -0
  32. data/lib/protos/command/trigger.rb +19 -0
  33. data/lib/protos/command.rb +49 -0
  34. data/lib/protos/component.rb +79 -0
  35. data/lib/protos/drawer/content.rb +19 -0
  36. data/lib/protos/drawer/side.rb +25 -0
  37. data/lib/protos/drawer/trigger.rb +21 -0
  38. data/lib/protos/drawer.rb +35 -0
  39. data/lib/protos/dropdown/item.rb +11 -0
  40. data/lib/protos/dropdown/menu.rb +25 -0
  41. data/lib/protos/dropdown/trigger.rb +11 -0
  42. data/lib/protos/dropdown.rb +59 -0
  43. data/lib/protos/engine.rb +7 -0
  44. data/lib/protos/list/item.rb +22 -0
  45. data/lib/protos/list.rb +30 -0
  46. data/lib/protos/modal/close_button.rb +16 -0
  47. data/lib/protos/modal/dialog.rb +30 -0
  48. data/lib/protos/modal/trigger.rb +19 -0
  49. data/lib/protos/modal.rb +31 -0
  50. data/lib/protos/popover/content.rb +19 -0
  51. data/lib/protos/popover/trigger.rb +11 -0
  52. data/lib/protos/popover.rb +54 -0
  53. data/lib/protos/table/body.rb +11 -0
  54. data/lib/protos/table/caption.rb +19 -0
  55. data/lib/protos/table/cell.rb +11 -0
  56. data/lib/protos/table/footer.rb +11 -0
  57. data/lib/protos/table/head.rb +11 -0
  58. data/lib/protos/table/header.rb +11 -0
  59. data/lib/protos/table/row.rb +11 -0
  60. data/lib/protos/table.rb +48 -0
  61. data/lib/protos/theme.rb +76 -0
  62. data/lib/protos/timeline/center.rb +19 -0
  63. data/lib/protos/timeline/item.rb +11 -0
  64. data/lib/protos/timeline/left.rb +19 -0
  65. data/lib/protos/timeline/right.rb +19 -0
  66. data/lib/protos/timeline.rb +38 -0
  67. data/lib/protos/token_list.rb +41 -0
  68. data/lib/protos/types.rb +32 -0
  69. data/lib/protos/typography/heading.rb +44 -0
  70. data/lib/protos/typography/inline_link.rb +24 -0
  71. data/lib/protos/typography/paragraph.rb +22 -0
  72. data/lib/protos/typography.rb +29 -0
  73. data/lib/protos/version.rb +5 -0
  74. data/lib/protos.rb +94 -0
  75. data/protos.gemspec +45 -0
  76. 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,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Protos
4
+ class Command
5
+ class Group < Component
6
+ def template(&block)
7
+ li(**attrs) do
8
+ ul(class: css[:list], &block)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ 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 List < Component
6
+ def template(&block)
7
+ ul(**attrs, &block)
8
+ end
9
+
10
+ private
11
+
12
+ def theme
13
+ {
14
+ container: tokens("menu")
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 Title < Component
6
+ def template(&block)
7
+ h2(**attrs, &block)
8
+ end
9
+
10
+ private
11
+
12
+ def theme
13
+ {
14
+ container: tokens("menu-title")
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,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Protos
4
+ class Dropdown
5
+ class Item < Component
6
+ def template(&block)
7
+ li(**attrs, &block)
8
+ end
9
+ end
10
+ end
11
+ 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,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Protos
4
+ class Dropdown
5
+ class Trigger < Component
6
+ def template(&block)
7
+ summary(**attrs, &block)
8
+ end
9
+ end
10
+ end
11
+ 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,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Protos
4
+ class Engine < ::Rails::Engine
5
+ config.autoload_paths += Dir["#{config.root}/lib/"]
6
+ end
7
+ 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