organism-ui 0.2.1 → 0.2.16

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3065e937e87ba2c40e0b8a30d1c57402330b7c4452faea8d6220e7188906d2fd
4
- data.tar.gz: 30cee7eb57cc13b3002c328465c215040e9dbff0e8a86d915005200c46305352
3
+ metadata.gz: 45abc828f8e47547304444edd15b9ffb4ec4377feb286c5559fe4c60d6e23dfd
4
+ data.tar.gz: 411a58b849148a4f9c1635a8a318784bc25421a4b146a4911ce0bc4c1cec4dfb
5
5
  SHA512:
6
- metadata.gz: 2c314d87dc4192fd479015a1b6ae10ad238bb4e5a22b19c5d7a9fb5d31d6b16bd801dff97dbd26743b5931159dd6a3f92e88e3f3116d66a1860451c31bfda36a
7
- data.tar.gz: db8edc5cc1a98bb8deb6da1eae88b000d14211d561a47492d221eacbfd474e773e3ea267b71861d523db95b11739fa52ae0c7e83c87b3bce530a462e53ec0dcf
6
+ metadata.gz: db0d57b58f82cd7cf96aa9afad5f6862f7ce8b11652e383ca1ac13b5b38c4c1d360b4c6ad9bdbb66d28926f8c9cc66f657efc16ccab365ed5df8bbd3b6ce6649
7
+ data.tar.gz: d75702678ac862483be221af7bd4a3a19fc60e502767214a14688ca2710814b893a33c1a7907857d9b6631596f13dd24425e051148249bf569656a0c57f9fb1b
data/README.md CHANGED
@@ -1,14 +1,27 @@
1
- # Ui
2
- Short description and motivation.
1
+ # Organism Ui
2
+ Ui components made with cells (https://github.com/trailblazer/cells). This library is in ALPHA and subject to change anytime and dramatically before 1.0.
3
3
 
4
4
  ## Usage
5
- How to use my plugin.
5
+
6
+ ### Components
7
+ Components are just configurable cells (https://github.com/trailblazer/cells) for basic ui components. Inspired by ant.design.
8
+
9
+ You render components in your views or controllers:
10
+ ```ruby
11
+ <%= cell(
12
+ Ui::Buttons::Primary,
13
+ 'Primary Button',
14
+ path: '/'
15
+ ) %>
16
+ ```
17
+
18
+ You can see full examples of components in the style guide: https://github.com/nolantait/organism-ui/blob/master/app/views/ui/style_guide/show.html.erb
6
19
 
7
20
  ## Installation
8
21
  Add this line to your application's Gemfile:
9
22
 
10
23
  ```ruby
11
- gem 'ui'
24
+ gem 'organism-ui'
12
25
  ```
13
26
 
14
27
  And then execute:
@@ -18,9 +31,20 @@ $ bundle
18
31
 
19
32
  Or install it yourself as:
20
33
  ```bash
21
- $ gem install ui
34
+ $ gem install organism-ui
22
35
  ```
23
36
 
37
+ ## Style guide
38
+ To quickly style your components you can mount the engine and navigate to an example style guide.
39
+
40
+ ```ruby
41
+ Rails.application.routes.draw do
42
+ mount Ui::Engine => "/ui"
43
+ end
44
+ ```
45
+
46
+ You can then navigate to localhost:3000/ui/style_guide to see your components.
47
+
24
48
  ## Contributing
25
49
  Contribution directions go here.
26
50
 
@@ -674,11 +674,10 @@
674
674
  ).()
675
675
  }
676
676
  ],
677
- renderable: ->(item) {
677
+ item_renderer: ->(item) {
678
678
  content_tag(
679
679
  :div,
680
- [
681
- content_tag(:p, item),
680
+ content_tag(:p, item) +
682
681
  content_tag(
683
682
  :nav,
684
683
  cell(
@@ -687,8 +686,7 @@
687
686
  path: '#',
688
687
  size: :small
689
688
  ).call(:edit)
690
- )
691
- ].join(' ').html_safe,
689
+ ),
692
690
  class: 'flex flex-row justify-between items-center p-4'
693
691
  )
694
692
  }
@@ -727,6 +725,32 @@
727
725
  </div>
728
726
  </section>
729
727
 
728
+ <section class="style-guide__example" id="type">
729
+ <header>
730
+ <h2>Vertical</h2>
731
+ </header>
732
+
733
+ <div class="space-y-4">
734
+ <%= cell(
735
+ Ui::Table,
736
+ [
737
+ "Data 1",
738
+ "Data 2",
739
+ "Data 3",
740
+ ],
741
+ columns: [
742
+ ["", ->(data) { data } ],
743
+ ["Column 2", ->(data) { "Column 2 data" } ],
744
+ ["Column 3", ->(data) { "Column 3 data" } ],
745
+ ["Actions", ->(data) { cell(Ui::Buttons::Tertiary, 'More')} ],
746
+ ],
747
+ header: 'My title',
748
+ orientation: 'vertical',
749
+ style: 'my-style'
750
+ ).() %>
751
+ </div>
752
+ </section>
753
+
730
754
  <section class="style-guide__example" id="type">
731
755
  <header>
732
756
  <h2>Selectable</h2>
@@ -748,6 +772,8 @@
748
772
  ],
749
773
  header: 'Multi select',
750
774
  style: 'my-style',
775
+ row_renderer: ->(row, columns) {
776
+ },
751
777
  features: {
752
778
  selectable: {
753
779
  multiple: true
data/lib/ui.rb CHANGED
@@ -4,6 +4,8 @@ require "cells-erb"
4
4
  require "cells-rails"
5
5
  require 'dry-struct'
6
6
 
7
+ require "ui/errors/base"
8
+
7
9
  require "ui/types"
8
10
  require "ui/value"
9
11
 
data/lib/ui/actionable.rb CHANGED
@@ -1,11 +1,26 @@
1
1
  module Ui
2
2
  module Actionable
3
- def actions
4
- render_group(
5
- options.fetch(:actions, Array.new).map do |action|
6
- action.call(model)
7
- end
8
- )
3
+ Actions = Types::Array.default([].freeze).of(Types::Callable)
4
+
5
+ def actions(object = model)
6
+ content_tag(:nav, class: 'ui-actions', role: 'navigation') do
7
+ render_group(
8
+ actions_list.map do |action|
9
+ action.call(object)
10
+ end
11
+ )
12
+ end
13
+ end
14
+
15
+ def actions_list
16
+ begin
17
+ Actions[options.fetch(:actions, Array.new)]
18
+ rescue Dry::Types::ConstraintError
19
+ raise Ui::Errors::InvalidActions.new(
20
+ "Actions for #{self.class.to_s} are invalid. Ensure you are passing " \
21
+ "an array of callable objects that will be passed a model"
22
+ )
23
+ end
9
24
  end
10
25
 
11
26
  def actions_length
@@ -13,7 +28,7 @@ module Ui
13
28
  end
14
29
 
15
30
  def has_actions?
16
- options.fetch(:actions, []).any?
31
+ actions_list.any?
17
32
  end
18
33
  end
19
34
  end
@@ -1,9 +1,9 @@
1
1
  module Ui
2
2
  class Breadcrumbs < Component
3
+ include Stylable
4
+
3
5
  def show
4
- content_tag(:nav, class: 'ui-breadcrumbs') do
5
- breadcrumb_links
6
- end
6
+ content_tag(:nav, render_group(breadcrumb_links.flatten), class: style)
7
7
  end
8
8
 
9
9
  private
@@ -14,10 +14,10 @@ module Ui
14
14
 
15
15
  def breadcrumb_links
16
16
  breadcrumbs.map.with_index do |crumb, index|
17
- [item_renderer.call(crumb)].tap do |renderable|
18
- renderable.unshift(delimiter) unless index == 0
17
+ [item_renderer.call(crumb)].tap do |array|
18
+ array.unshift(delimiter) unless index == 0
19
19
  end
20
- end.flatten.join(' ').html_safe
20
+ end
21
21
  end
22
22
 
23
23
  def delimiter
@@ -25,7 +25,20 @@ module Ui
25
25
  end
26
26
 
27
27
  def item_renderer
28
- options[:item_renderer] || Ui::Breadcrumbs::Breadcrumb
28
+ options[:item_renderer] || default_item_renderer
29
+ end
30
+
31
+ def default_item_renderer
32
+ ->(item) {
33
+ cell(
34
+ Ui::Breadcrumbs::Breadcrumb,
35
+ item
36
+ ).()
37
+ }
38
+ end
39
+
40
+ def component_style
41
+ 'ui-breadcrumbs'
29
42
  end
30
43
  end
31
44
  end
@@ -1,6 +1,8 @@
1
1
  module Ui
2
2
  class Breadcrumbs < Component
3
3
  class Breadcrumb < Component
4
+ include Stylable
5
+
4
6
  property :name
5
7
  property :path
6
8
  property :current?
@@ -9,9 +11,7 @@ module Ui
9
11
  def show
10
12
  content_tag(
11
13
  :span,
12
- link_to(path) do
13
- title.html_safe
14
- end,
14
+ link_to(render_group(title), path),
15
15
  class: style
16
16
  )
17
17
  end
@@ -19,17 +19,19 @@ module Ui
19
19
  private
20
20
 
21
21
  def title
22
- [name].tap do |array|
23
- array.unshift(content_tag(:i, nil, class: icon)) if model.try(:icon)
24
- end.join(' ')
22
+ [content_tag(:span, name)].tap do |array|
23
+ array.unshift(content_tag(:i, nil, class: icon)) if has_icon?
24
+ end
25
25
  end
26
26
 
27
- def style
28
- [
29
- 'breadcrumb'
30
- ].tap do |array|
31
- array << 'breadcrumb--current' if current?
32
- end
27
+ def has_icon?
28
+ model.try(:icon)
29
+ end
30
+
31
+ def component_style
32
+ ['ui-breadcrumb'].tap do |array|
33
+ array << 'ui-breadcrumb--current' if current?
34
+ end.join(' ')
33
35
  end
34
36
  end
35
37
  end
@@ -1,6 +1,8 @@
1
1
  module Ui
2
2
  module Buttons
3
3
  class Base < Component
4
+ include Stylable
5
+
4
6
  def show
5
7
  display(
6
8
  text_with_icon(icon),
@@ -38,6 +40,22 @@ module Ui
38
40
  )
39
41
  end
40
42
 
43
+ def phone
44
+ display(
45
+ text_with_icon(phone_icon),
46
+ "tel:#{path}",
47
+ button_options
48
+ )
49
+ end
50
+
51
+ def email
52
+ mail_to(
53
+ path,
54
+ text_with_icon(email_icon),
55
+ button_options
56
+ )
57
+ end
58
+
41
59
  private
42
60
 
43
61
  def display(*args)
@@ -46,7 +64,7 @@ module Ui
46
64
  :button,
47
65
  args.first,
48
66
  disabled: true,
49
- class: button_classes
67
+ class: style
50
68
  )
51
69
  else
52
70
  if path == '#'
@@ -69,13 +87,12 @@ module Ui
69
87
  'fas fa-trash'
70
88
  end
71
89
 
72
- def button_classes
73
- [
74
- "button",
75
- style,
76
- size,
77
- options.fetch(:style, '')
78
- ].compact.join(' ')
90
+ def phone_icon
91
+ 'fas fa-phone'
92
+ end
93
+
94
+ def email_icon
95
+ 'fas fa-envelope'
79
96
  end
80
97
 
81
98
  def size
@@ -92,25 +109,40 @@ module Ui
92
109
  end
93
110
 
94
111
  def text_with_icon(icon)
95
- if icon
96
- content_tag(
97
- :span,
98
- render_group([
99
- content_tag(:i, nil, class: icon),
100
- text
101
- ].compact)
102
- )
103
- else
104
- text
112
+ order = [text].tap do |array|
113
+ case icon_position
114
+ when 'end'
115
+ array.push(display_icon(icon))
116
+ else
117
+ array.unshift(display_icon(icon))
118
+ end
105
119
  end
120
+
121
+ render_group(order)
122
+ end
123
+
124
+ def display_icon(icon)
125
+ content_tag(:i, nil, class: icon) unless icon.blank?
106
126
  end
107
127
 
108
- def style
109
- ''
128
+ def component_style
129
+ [
130
+ 'button',
131
+ size,
132
+ ].join(' ')
110
133
  end
111
134
 
112
135
  def icon
113
- options[:icon]
136
+ icon_options.fetch(:style, '')
137
+ end
138
+
139
+ def icon_position
140
+ icon_options.fetch(:position, 'start')
141
+ end
142
+
143
+ def icon_options
144
+ opts = options.fetch(:icon, {})
145
+ opts.is_a?(Hash) ? opts : { style: opts }
114
146
  end
115
147
 
116
148
  def path
@@ -135,7 +167,7 @@ module Ui
135
167
 
136
168
  def button_options
137
169
  {
138
- class: button_classes,
170
+ class: style,
139
171
  disabled: disabled?,
140
172
  data: data,
141
173
  method: method
@@ -3,8 +3,11 @@ module Ui
3
3
  class Primary < Base
4
4
  private
5
5
 
6
- def style
7
- 'button--primary'
6
+ def component_style
7
+ [
8
+ 'button--primary',
9
+ super
10
+ ].flatten
8
11
  end
9
12
  end
10
13
  end
@@ -3,8 +3,11 @@ module Ui
3
3
  class Secondary < Base
4
4
  private
5
5
 
6
- def style
7
- 'button--secondary'
6
+ def component_style
7
+ [
8
+ 'button--secondary',
9
+ super
10
+ ].flatten
8
11
  end
9
12
  end
10
13
  end
@@ -3,8 +3,11 @@ module Ui
3
3
  class Tertiary < Base
4
4
  private
5
5
 
6
- def style
7
- 'button--tertiary'
6
+ def component_style
7
+ [
8
+ 'button--tertiary',
9
+ super
10
+ ].flatten
8
11
  end
9
12
  end
10
13
  end
data/lib/ui/card.rb CHANGED
@@ -16,9 +16,7 @@ module Ui
16
16
  end
17
17
 
18
18
  def card_actions
19
- content_tag(:nav, class: "ui-card__controls") do
20
- actions
21
- end if has_actions?
19
+ actions if has_actions?
22
20
  end
23
21
 
24
22
  def title
data/lib/ui/collapse.rb CHANGED
@@ -13,7 +13,8 @@ module Ui
13
13
  def panels
14
14
  cell(
15
15
  Ui::Collapse::Panel,
16
- collection: model
16
+ collection: model,
17
+ actions: options[:actions]
17
18
  ).()
18
19
  end
19
20
 
@@ -1,6 +1,8 @@
1
1
  module Ui
2
2
  class Collapse < Component
3
3
  class Panel < Component
4
+ include Actionable
5
+
4
6
  def show
5
7
  render
6
8
  end
@@ -18,11 +20,11 @@ module Ui
18
20
  end
19
21
 
20
22
  def header
21
- content_tag(:p, display(model[0]))
23
+ display(model[0])
22
24
  end
23
25
 
24
26
  def content
25
- content_tag(:p, display(model[1]))
27
+ display(model[1])
26
28
  end
27
29
 
28
30
  def display(item)
@@ -1,16 +1,17 @@
1
1
  <article
2
2
  class="ui-collapse-panel"
3
3
  data-controller="collapsable"
4
- data-collapsable-collapsed-value="false"
4
+ data-collapsable-collapsed-value="true"
5
5
  data-collapsable-hidden-class="hidden"
6
6
  data-collapsable-collapsed-class="ui-collapsed">
7
7
 
8
- <header data-action="click->collapsable#toggle">
8
+ <header data-action="click->collapsable#toggle" class="ui-collapse-panel__header">
9
9
  <%= collapse_icon %>
10
10
  <%= header %>
11
+ <%= actions %>
11
12
  </header>
12
13
 
13
- <div data-collapsable-target="content" class="ui-collapse-panel__content">
14
+ <section data-collapsable-target="content" class="ui-collapse-panel__content">
14
15
  <%= content %>
15
- </div>
16
+ </section>
16
17
  </article>
data/lib/ui/component.rb CHANGED
@@ -6,10 +6,15 @@ module Ui
6
6
  include ActionView::Context
7
7
 
8
8
  VIEWPATH = Pathname.new(__FILE__).join("../..")
9
- self.view_paths = [VIEWPATH]
9
+ self.view_paths << VIEWPATH
10
10
 
11
11
  def capture(*args)
12
- yield(*args).html_safe
12
+ content = yield(*args)
13
+ if content.is_a?(String)
14
+ content.html_safe
15
+ else
16
+ content
17
+ end
13
18
  end
14
19
 
15
20
  def render_group(items)
@@ -25,14 +25,14 @@ module Ui
25
25
  content_tag(
26
26
  :header,
27
27
  render_group([
28
- content_tag(:h2, title),
29
- content_tag(:nav, actions)
28
+ options[:header],
29
+ actions
30
30
  ])
31
- ) if title || has_actions?
31
+ ) if display_header?
32
32
  end
33
33
 
34
- def title
35
- options[:title]
34
+ def display_header?
35
+ options[:header] || has_actions?
36
36
  end
37
37
 
38
38
  def items
@@ -5,19 +5,33 @@ module Ui
5
5
  content_tag(
6
6
  :div,
7
7
  render_group([
8
- content_tag(:dt, title),
9
- content_tag(:dd, value.html_safe)
8
+ content_tag(:dt, item_title),
9
+ content_tag(:dd, value)
10
10
  ]),
11
11
  class: 'ui-descriptive-list__item'
12
12
  )
13
13
  end
14
14
 
15
- def title
15
+ def value
16
+ render_group([
17
+ display(item_value)
18
+ ])
19
+ end
20
+
21
+ def display(value)
22
+ if value.is_a?(Proc)
23
+ value.call
24
+ else
25
+ value
26
+ end
27
+ end
28
+
29
+ def item_title
16
30
  model[0]
17
31
  end
18
32
 
19
- def value
20
- model[1].try(:call) || model[1]
33
+ def item_value
34
+ model[1]
21
35
  end
22
36
  end
23
37
  end
data/lib/ui/dropdown.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  module Ui
2
2
  class Dropdown < Component
3
+ include Stylable
4
+
3
5
  Modes = Types::String.enum(
4
6
  'click',
5
7
  'hover'
@@ -18,5 +20,9 @@ module Ui
18
20
  def mode
19
21
  Modes[options.fetch(:mode, 'click')]
20
22
  end
23
+
24
+ def component_style
25
+ "ui-dropdown"
26
+ end
21
27
  end
22
28
  end
@@ -4,7 +4,7 @@
4
4
  data-dropdown-expanded-value="false"
5
5
  data-dropdown-mode-value="<%= mode %>"
6
6
  data-action="click->dropdown#toggle"
7
- class="ui-dropdown">
7
+ class="<%= style %>">
8
8
  <%= yield %>
9
9
 
10
10
  <div data-dropdown-target="expandable" class="ui-dropdown__expandable">
@@ -4,8 +4,6 @@
4
4
 
5
5
  <figcaption>
6
6
  <%= caption %>
7
- <nav>
8
- <%= actions %>
9
- </nav>
7
+ <%= actions %>
10
8
  </figcaption>
11
9
  </figure>
data/lib/ui/engine.rb CHANGED
@@ -2,6 +2,8 @@ module Ui
2
2
  class Engine < ::Rails::Engine
3
3
  isolate_namespace Ui
4
4
 
5
+ config.autoload_paths << "#{config.root}/lib"
6
+
5
7
  config.generators do |g|
6
8
  g.test_framework :rspec, fixture: false
7
9
  g.fixture_replacement :factory_bot
@@ -0,0 +1,6 @@
1
+ module Ui
2
+ module Errors
3
+ class Base < StandardError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Ui
2
+ module Errors
3
+ class InvalidActions < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Ui
2
+ module Errors
3
+ class InvalidListItems < Base
4
+ end
5
+ end
6
+ end
data/lib/ui/list.rb CHANGED
@@ -4,6 +4,7 @@ module Ui
4
4
  include Actionable
5
5
 
6
6
  Renderable = Types.Interface(:call)
7
+ ListItems = Types.Interface(:each, :map, :any?)
7
8
 
8
9
  def show
9
10
  render
@@ -11,21 +12,32 @@ module Ui
11
12
 
12
13
  private
13
14
 
15
+ def list_data
16
+ begin
17
+ ListItems[model]
18
+ rescue Dry::Types::ConstraintError
19
+ raise Ui::Errors::InvalidListItems.new(
20
+ "List items for #{self.class.to_s} are invalid. Ensure you are passing " \
21
+ "an empty array or array of items that will be passed to the item renderer"
22
+ )
23
+ end
24
+ end
25
+
14
26
  def list
15
27
  content_tag(:ul, list_items)
16
28
  end
17
29
 
18
30
  def list_items
19
- if list_data.any?
20
- render_group(list_data)
31
+ if rendered_items.any?
32
+ render_group(rendered_items)
21
33
  else
22
34
  render_empty
23
35
  end
24
36
  end
25
37
 
26
- def list_data
27
- model.map do |item|
28
- renderable.call(item)
38
+ def rendered_items
39
+ list_data.map do |item|
40
+ item_renderer.call(item)
29
41
  end
30
42
  end
31
43
 
@@ -46,8 +58,8 @@ module Ui
46
58
  ) if options[:footer]
47
59
  end
48
60
 
49
- def renderable
50
- Renderable[options.fetch(:renderable, default_renderable)]
61
+ def item_renderer
62
+ Renderable[options.fetch(:item_renderer, default_renderable)]
51
63
  end
52
64
 
53
65
  def default_renderable
@@ -68,6 +80,10 @@ module Ui
68
80
  end
69
81
 
70
82
  def empty
83
+ options.fetch(:empty, default_empty)
84
+ end
85
+
86
+ def default_empty
71
87
  cell(
72
88
  Ui::Empty,
73
89
  nil
data/lib/ui/menu/item.rb CHANGED
@@ -24,7 +24,7 @@ module Ui
24
24
  private
25
25
 
26
26
  def render_item
27
- model.html_safe
27
+ model
28
28
  end
29
29
 
30
30
  def depth
@@ -9,7 +9,7 @@ module Ui
9
9
  :ul,
10
10
  render_group([
11
11
  previous_window,
12
- page_links.html_safe,
12
+ page_links,
13
13
  next_window
14
14
  ]),
15
15
  class: 'ui-pagination__window',
@@ -58,15 +58,17 @@ module Ui
58
58
 
59
59
 
60
60
  def page_links
61
- pages.inject('') do |content, page|
62
- content += content_tag(
63
- :li,
64
- cell(
65
- Ui::Pagination::PageLink,
66
- page
67
- ).()
68
- )
69
- end
61
+ render_group(
62
+ pages.map do |page|
63
+ content_tag(
64
+ :li,
65
+ cell(
66
+ Ui::Pagination::PageLink,
67
+ page
68
+ ).()
69
+ )
70
+ end
71
+ )
70
72
  end
71
73
 
72
74
  def last_window?
data/lib/ui/table.rb CHANGED
@@ -1,10 +1,21 @@
1
1
  require "ui/table/header"
2
2
  require "ui/table/row"
3
+ require "ui/table/vertical"
3
4
 
4
5
  module Ui
5
6
  class Table < Component
6
7
  include Actionable
7
8
  include Stylable
9
+ include ::Cell::Builder
10
+
11
+ builds do |model, options|
12
+ case options.fetch(:orientation, 'horizontal')
13
+ when 'vertical'
14
+ Ui::Table::Vertical
15
+ else
16
+ self
17
+ end
18
+ end
8
19
 
9
20
  def show
10
21
  render
@@ -22,6 +33,20 @@ module Ui
22
33
  end
23
34
 
24
35
  def table_headers
36
+ custom_header_renderer.is_a?(Proc) ?
37
+ custom_table_headers :
38
+ default_table_headers
39
+ end
40
+
41
+ def custom_table_headers
42
+ render_group(
43
+ columns.map do |column|
44
+ custom_header_renderer.call(column)
45
+ end
46
+ )
47
+ end
48
+
49
+ def default_table_headers
25
50
  content_tag(:tr) do
26
51
  cell(
27
52
  Ui::Table::Header,
@@ -31,31 +56,53 @@ module Ui
31
56
  end
32
57
 
33
58
  def table_rows
34
- if rows.any?
35
- cell(
36
- Ui::Table::Row,
37
- collection: rows,
38
- columns: columns
39
- )
59
+ if model.any?
60
+ custom_row_renderer.is_a?(Proc) ?
61
+ custom_table_rows :
62
+ default_table_rows
40
63
  else
41
64
  render_empty
42
65
  end
43
66
  end
44
67
 
68
+ def custom_table_rows
69
+ render_group(
70
+ model.map do |row|
71
+ custom_row_renderer.call(row, columns)
72
+ end
73
+ )
74
+ end
75
+
76
+ def default_table_rows
77
+ cell(
78
+ Ui::Table::Row,
79
+ collection: model,
80
+ columns: columns
81
+ ).()
82
+ end
83
+
45
84
  def table_data_attributes
46
85
  {
47
86
  controller: table_controllers,
48
- "selectable-selected-value": "[]",
49
- "selectable-type-value": multi_select? ? 'many' : 'one'
50
- }
87
+ }.tap do |hash|
88
+ if selectable?
89
+ hash["selectable-selected-value"] = "[]"
90
+ hash["selectable-type-value"] = multi_select? ? 'many' : 'one'
91
+ end
92
+ end
51
93
  end
52
94
 
53
95
  def table_body_data_attributes
54
96
  {
55
97
  controller: table_body_controllers,
56
- "sortable-update-url-value": sortable_options.fetch(:update_url, '#'),
57
- "sortable-input-name-value": sortable_options.fetch(:input_name, "object[position]")
58
- }
98
+ }.tap do |hash|
99
+ if sortable?
100
+ hash["sortable-update-url-value"] =
101
+ sortable_options.fetch(:update_url, '#')
102
+ hash["sortable-input-name-value"] =
103
+ sortable_options.fetch(:input_name, "object[position]")
104
+ end
105
+ end
59
106
  end
60
107
 
61
108
  def table_controllers
@@ -87,10 +134,6 @@ module Ui
87
134
  ) if options[:footer]
88
135
  end
89
136
 
90
- def component_style
91
- "ui-table"
92
- end
93
-
94
137
  def columns
95
138
  @columns ||= options.fetch(:columns, Array.new).tap do |columns|
96
139
  columns.unshift(selectable_column) if selectable?
@@ -140,8 +183,12 @@ module Ui
140
183
  options.fetch(:features, Hash.new)
141
184
  end
142
185
 
143
- def rows
144
- model
186
+ def custom_row_renderer
187
+ options.fetch(:row_renderer, nil)
188
+ end
189
+
190
+ def custom_header_renderer
191
+ options.fetch(:header_renderer, nil)
145
192
  end
146
193
 
147
194
  def render_empty
@@ -158,5 +205,9 @@ module Ui
158
205
  colspan: columns.size
159
206
  )
160
207
  end
208
+
209
+ def component_style
210
+ "ui-table ui-table--horizontal"
211
+ end
161
212
  end
162
213
  end
@@ -1,20 +1,30 @@
1
1
  module Ui
2
2
  class Table < Component
3
3
  class Header < Component
4
+ include Stylable
5
+
4
6
  def show
5
- content_tag(:th, title)
7
+ content_tag(:th, title, class: style)
6
8
  end
7
9
 
8
10
  private
9
11
 
12
+ def component_style
13
+ 'ui-table__header'
14
+ end
15
+
10
16
  def title
11
17
  case
12
- when model[0].is_a?(Proc)
13
- model[0].call
18
+ when column_title.is_a?(Proc)
19
+ column_title.call
14
20
  else
15
- model[0]
21
+ column_title
16
22
  end
17
23
  end
24
+
25
+ def column_title
26
+ model[0]
27
+ end
18
28
  end
19
29
  end
20
30
  end
data/lib/ui/table/row.rb CHANGED
@@ -1,12 +1,18 @@
1
1
  module Ui
2
2
  class Table < Component
3
3
  class Row < Component
4
+ include Stylable
5
+
4
6
  def show
5
- content_tag(:tr, render_group(table_data))
7
+ content_tag(:tr, render_group(table_data), class: style)
6
8
  end
7
9
 
8
10
  private
9
11
 
12
+ def component_style
13
+ 'ui-table__row'
14
+ end
15
+
10
16
  def table_data
11
17
  columns.map do |column|
12
18
  content_tag(:td, apply(column))
@@ -0,0 +1,45 @@
1
+ module Ui
2
+ class Table < Component
3
+ class Vertical < Table
4
+
5
+ private
6
+
7
+ def table_rows
8
+ if model.any?
9
+ cell(
10
+ row_renderer,
11
+ collection: columns[1..-1],
12
+ data: model
13
+ )
14
+ else
15
+ render_empty
16
+ end
17
+ end
18
+
19
+ def table_headers
20
+ content_tag(:tr) do
21
+ render_group([
22
+ content_tag(:th, columns[0].try(:first)),
23
+ cell(
24
+ header_renderer,
25
+ collection: model,
26
+ column: columns[0],
27
+ )
28
+ ])
29
+ end
30
+ end
31
+
32
+ def row_renderer
33
+ Ui::Table::Vertical::Row
34
+ end
35
+
36
+ def header_renderer
37
+ Ui::Table::Vertical::Header
38
+ end
39
+
40
+ def component_style
41
+ "ui-table ui-table--vertical"
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,26 @@
1
+ module Ui
2
+ class Table < Component
3
+ class Vertical < Table
4
+ class Header < Ui::Table::Header
5
+ def show
6
+ content_tag(:th, title)
7
+ end
8
+
9
+ private
10
+
11
+ def title
12
+ case
13
+ when column[1].is_a?(Proc)
14
+ column[1].call(model)
15
+ else
16
+ model.to_s
17
+ end
18
+ end
19
+
20
+ def column
21
+ options[:column]
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,34 @@
1
+ module Ui
2
+ class Table < Component
3
+ class Vertical < Table
4
+ class Row < Ui::Table::Row
5
+
6
+ private
7
+
8
+ def table_data
9
+ data.map do |item|
10
+ content_tag(:td, apply(item))
11
+ end.tap do |array|
12
+ array.unshift(content_tag(:th, column_title))
13
+ end
14
+ end
15
+
16
+ def apply(item)
17
+ column[1].call(item)
18
+ end
19
+
20
+ def column
21
+ model
22
+ end
23
+
24
+ def column_title
25
+ column[0]
26
+ end
27
+
28
+ def data
29
+ options.fetch(:data, Array.new)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
data/lib/ui/types.rb CHANGED
@@ -3,5 +3,7 @@ require 'dry-types'
3
3
  module Ui
4
4
  module Types
5
5
  include Dry.Types()
6
+
7
+ Callable = Types.Interface(:call)
6
8
  end
7
9
  end
data/lib/ui/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Ui
2
- VERSION = '0.2.1'
2
+ VERSION = '0.2.16'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: organism-ui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nolan Tait
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-13 00:00:00.000000000 Z
11
+ date: 2021-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -156,6 +156,20 @@ dependencies:
156
156
  - - "~>"
157
157
  - !ruby/object:Gem::Version
158
158
  version: 11.1.3
159
+ - !ruby/object:Gem::Dependency
160
+ name: sqlite3
161
+ requirement: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - "~>"
164
+ - !ruby/object:Gem::Version
165
+ version: 1.4.2
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - "~>"
171
+ - !ruby/object:Gem::Version
172
+ version: 1.4.2
159
173
  description: A collection of ui components implemented in cells.
160
174
  email:
161
175
  - nolanjtait@gmail.com
@@ -201,6 +215,9 @@ files:
201
215
  - lib/ui/empty.rb
202
216
  - lib/ui/empty/show.erb
203
217
  - lib/ui/engine.rb
218
+ - lib/ui/errors/base.rb
219
+ - lib/ui/errors/invalid_actions.rb
220
+ - lib/ui/errors/invalid_list_items.rb
204
221
  - lib/ui/list.rb
205
222
  - lib/ui/list/item.rb
206
223
  - lib/ui/list/show.erb
@@ -231,6 +248,9 @@ files:
231
248
  - lib/ui/table/select_all.rb
232
249
  - lib/ui/table/show.erb
233
250
  - lib/ui/table/sort.rb
251
+ - lib/ui/table/vertical.rb
252
+ - lib/ui/table/vertical/header.rb
253
+ - lib/ui/table/vertical/row.rb
234
254
  - lib/ui/tooltip.rb
235
255
  - lib/ui/tooltip/show.erb
236
256
  - lib/ui/types.rb
@@ -243,7 +263,7 @@ homepage: https://github.com/nolantait/organism-ui
243
263
  licenses:
244
264
  - MIT
245
265
  metadata: {}
246
- post_install_message:
266
+ post_install_message:
247
267
  rdoc_options: []
248
268
  require_paths:
249
269
  - lib
@@ -259,7 +279,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
259
279
  version: '0'
260
280
  requirements: []
261
281
  rubygems_version: 3.1.4
262
- signing_key:
282
+ signing_key:
263
283
  specification_version: 4
264
284
  summary: A collection of ui components implemented in cells.
265
285
  test_files: []