bulma_x 0.2.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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +22 -0
  4. data/CHANGELOG.md +30 -0
  5. data/CONTRIBUTING.md +50 -0
  6. data/LICENSE +661 -0
  7. data/README.md +315 -0
  8. data/Rakefile +12 -0
  9. data/lib/bulma_x/base_component.rb +125 -0
  10. data/lib/bulma_x/base_input.rb +37 -0
  11. data/lib/bulma_x/block.rb +7 -0
  12. data/lib/bulma_x/box.rb +7 -0
  13. data/lib/bulma_x/breadcrumbs.rb +35 -0
  14. data/lib/bulma_x/button.rb +42 -0
  15. data/lib/bulma_x/card.rb +55 -0
  16. data/lib/bulma_x/checkbox.rb +23 -0
  17. data/lib/bulma_x/columns.rb +81 -0
  18. data/lib/bulma_x/component_dsl.rb +19 -0
  19. data/lib/bulma_x/dropdown.rb +65 -0
  20. data/lib/bulma_x/dsl/options.rb +129 -0
  21. data/lib/bulma_x/dsl/slots.rb +234 -0
  22. data/lib/bulma_x/dsl/validations.rb +74 -0
  23. data/lib/bulma_x/field.rb +150 -0
  24. data/lib/bulma_x/figure.rb +27 -0
  25. data/lib/bulma_x/file.rb +54 -0
  26. data/lib/bulma_x/footer.rb +7 -0
  27. data/lib/bulma_x/form.rb +27 -0
  28. data/lib/bulma_x/grid.rb +90 -0
  29. data/lib/bulma_x/help.rb +7 -0
  30. data/lib/bulma_x/hero.rb +36 -0
  31. data/lib/bulma_x/icon.rb +66 -0
  32. data/lib/bulma_x/image.rb +42 -0
  33. data/lib/bulma_x/input.rb +53 -0
  34. data/lib/bulma_x/level.rb +43 -0
  35. data/lib/bulma_x/link.rb +44 -0
  36. data/lib/bulma_x/media.rb +19 -0
  37. data/lib/bulma_x/message.rb +27 -0
  38. data/lib/bulma_x/modal.rb +26 -0
  39. data/lib/bulma_x/navbar.rb +162 -0
  40. data/lib/bulma_x/notification.rb +15 -0
  41. data/lib/bulma_x/pagination.rb +86 -0
  42. data/lib/bulma_x/panel.rb +29 -0
  43. data/lib/bulma_x/paragraph.rb +7 -0
  44. data/lib/bulma_x/progress.rb +36 -0
  45. data/lib/bulma_x/radio.rb +33 -0
  46. data/lib/bulma_x/section.rb +35 -0
  47. data/lib/bulma_x/select.rb +57 -0
  48. data/lib/bulma_x/shared/aria_options.rb +19 -0
  49. data/lib/bulma_x/shared/data_options.rb +19 -0
  50. data/lib/bulma_x/shared/flex_options.rb +57 -0
  51. data/lib/bulma_x/shared/global_options.rb +49 -0
  52. data/lib/bulma_x/shared/spacing_options.rb +80 -0
  53. data/lib/bulma_x/shared/text_options.rb +31 -0
  54. data/lib/bulma_x/slot.rb +13 -0
  55. data/lib/bulma_x/subtitle.rb +9 -0
  56. data/lib/bulma_x/table.rb +78 -0
  57. data/lib/bulma_x/tabs.rb +43 -0
  58. data/lib/bulma_x/tag.rb +25 -0
  59. data/lib/bulma_x/textarea.rb +29 -0
  60. data/lib/bulma_x/title.rb +21 -0
  61. data/lib/bulma_x/version.rb +5 -0
  62. data/lib/bulma_x/vertical_menu.rb +71 -0
  63. data/lib/bulma_x.rb +9 -0
  64. metadata +123 -0
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Modal < BaseComponent
5
+ option :modifier, values: MODIFIERS, default: nil
6
+
7
+ slot :background, classes: ['modal-background']
8
+ slot :content, classes: ['modal-content']
9
+
10
+ def view_template(&)
11
+ super do
12
+ slot(:background) do
13
+ slot(:content, &)
14
+ end
15
+ end
16
+ end
17
+
18
+ def root_classes
19
+ super +
20
+ [
21
+ 'modal',
22
+ @modifier && "is-#{@modifier}"
23
+ ]
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Navbar < BaseComponent
5
+ option :style, values: [nil, 'boxed', 'transparent'], default: nil
6
+ option :modifier, values: MODIFIERS, default: nil
7
+ option :shadow, values: BOOLEAN, default: false
8
+ option :spaced, values: BOOLEAN, default: false
9
+ option :fixed, values: BOOLEAN, default: true
10
+
11
+ root_slot tag: :nav
12
+
13
+ slot :brand, tag: :div, classes: ['navbar-brand']
14
+ slot :burger, tag: :div, classes: ['navbar-burger']
15
+ slot :menu, component: 'NavbarMenu'
16
+
17
+ default_option :aria, { role: 'menubar', orientation: 'horizontal' }
18
+
19
+ def view_template
20
+ super do
21
+ if slot?(:brand)
22
+ slot(:brand) do
23
+ slot(:burger)
24
+ end
25
+ end
26
+
27
+ slot(:menu)
28
+ end
29
+ end
30
+
31
+ def root_classes
32
+ super +
33
+ [
34
+ 'navbar',
35
+ @style && "is-#{@style}",
36
+ @modifier && "is-#{@modifier}",
37
+ @shadow && 'has-shadow',
38
+ @spaced && 'is-spaced',
39
+ @fixed && 'is-fixed-top'
40
+ ]
41
+ end
42
+
43
+ class NavbarMenu < BulmaX::BaseComponent
44
+ slot :left, component: 'NavbarStart'
45
+ slot :right, component: 'NavbarEnd'
46
+
47
+ option :mobile, values: BOOLEAN, default: false
48
+
49
+ def root_classes
50
+ super + [
51
+ 'navbar-menu',
52
+ @mobile && 'is-active'
53
+ ]
54
+ end
55
+
56
+ def view_template
57
+ super do
58
+ slot(:left)
59
+ slot(:right)
60
+ end
61
+ end
62
+
63
+ class NavbarDropdown < BulmaX::BaseComponent
64
+ option :label
65
+
66
+ slots :dropdown_item, component: 'NavbarDropdownItem'
67
+
68
+ def view_template
69
+ super do
70
+ div(class: 'navbar-link') { @label }
71
+
72
+ slots(:dropdown_item).each do |dropdown_item|
73
+ render(dropdown_item)
74
+ end
75
+ end
76
+ end
77
+
78
+ class NavbarDropdownItem < BulmaX::BaseComponent
79
+ option :divider, values: BOOLEAN, default: false
80
+
81
+ slot :item, component: '::BulmaX::Navbar::NavbarMenu::NavbarItem'
82
+
83
+ def view_template
84
+ super do
85
+ slot(:item) unless @divider
86
+ end
87
+ end
88
+
89
+ def root_classes
90
+ if @divider
91
+ super + ['navbar-divider']
92
+ else
93
+ super + ['navbar-dropdown']
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ class NavbarItem < BulmaX::BaseComponent
100
+ option :href
101
+ option :hoverable, values: BOOLEAN, default: true
102
+ option :active, values: BOOLEAN, default: false
103
+
104
+ slot :dropdown, component: NavbarDropdown
105
+
106
+ def root_tag
107
+ if slot?(:dropdown)
108
+ :div
109
+ else
110
+ :a
111
+ end
112
+ end
113
+
114
+ def root_attributes
115
+ if root_tag == :a
116
+ super.merge(href: @href)
117
+ else
118
+ super
119
+ end
120
+ end
121
+
122
+ def root_classes
123
+ extra_classes = ['navbar-item']
124
+ extra_classes << 'has-dropdown' if slot?(:dropdown)
125
+ extra_classes << 'is-active' if @active
126
+
127
+ extra_classes << 'is-hoverable' if @hoverable
128
+
129
+ super + extra_classes
130
+ end
131
+
132
+ def view_template
133
+ super do
134
+ if slot?(:dropdown)
135
+ slot(:dropdown)
136
+ elsif block_given?
137
+ yield
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ class NavbarStart < BulmaX::BaseComponent
144
+ slots :item, component: NavbarItem
145
+
146
+ def root_classes = super + ['navbar-start']
147
+
148
+ def view_template
149
+ super do
150
+ slots(:item).each do |item|
151
+ render(item)
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ class NavbarEnd < NavbarStart
158
+ def root_classes = super - ['navbar-start'] + ['navbar-end']
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Notification < BaseComponent
5
+ option :modifier, values: MODIFIERS, default: nil
6
+
7
+ def root_classes
8
+ super +
9
+ [
10
+ 'notification',
11
+ @modifier && "is-#{@modifier}"
12
+ ]
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ # TODO: Allow to reorder pagination's items as we want
5
+ class Pagination < BaseComponent
6
+ option :alignment, values: %i[left centered right], default: :centered
7
+ option :rounded, values: BOOLEAN, default: false
8
+ option :size, values: %i[small medium large], default: :medium
9
+
10
+ root_slot tag: :nav, attributes: { role: 'navigation', 'aria-label' => 'pagination' }
11
+ slot :list, component: 'List'
12
+ slot :previous, component: 'NavigationItem'
13
+ slot :next, component: 'NavigationItem'
14
+
15
+ def view_template
16
+ super do
17
+ slot(:list) do
18
+ slots(:item).each { render it }
19
+ end
20
+
21
+ slot(:previous, type: :previous) if slot?(:previous)
22
+ slot(:next, type: :next) if slot?(:next)
23
+ end
24
+ end
25
+
26
+ def root_classes
27
+ super + [
28
+ 'pagination',
29
+ "is-#{@alignment}",
30
+ @rounded && 'is-rounded',
31
+ "is-#{@size}"
32
+ ]
33
+ end
34
+
35
+ class NavigationItem < BaseComponent
36
+ option :href
37
+ option :type, values: %i[previous next]
38
+
39
+ def root_attributes = super.merge(href: @href)
40
+ def root_classes = super + ["pagination-#{@type}"]
41
+ def root_tag = :a
42
+ end
43
+
44
+ class List < BaseComponent
45
+ root_slot tag: :ul, classes: ['pagination-list']
46
+ slots :item, component: 'Item'
47
+
48
+ def view_template
49
+ super do
50
+ slots(:item).each do |item|
51
+ li do
52
+ render item
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ class Item < BaseComponent
59
+ option :current, values: BOOLEAN, default: false
60
+ option :href
61
+ option :type, values: %i[ellipsis link], default: :link
62
+
63
+ def view_template
64
+ super do
65
+ if block_given?
66
+ yield
67
+ elsif @type == :ellipsis
68
+ plain('…')
69
+ end
70
+ end
71
+ end
72
+
73
+ def root_tag = :a
74
+
75
+ def root_classes
76
+ super + [
77
+ @current && 'is-current',
78
+ "pagination-#{@type}"
79
+ ]
80
+ end
81
+
82
+ def root_attributes = super.merge(href: @href)
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ # TODO: Enable the slots to be ordered in different ways
5
+ # TODO: Tabs should only have <a> elements, use a dedicated sub-component
6
+ class Panel < BaseComponent
7
+ option :modifier, values: MODIFIERS, default: nil
8
+
9
+ slot :header, classes: ['panel-heading']
10
+ slots :block, classes: ['panel-block']
11
+ slot :tabs, classes: ['panel-tabs']
12
+
13
+ def view_template
14
+ super do
15
+ slot(:header) if slot?(:header)
16
+ slot(:tabs) if slot?(:tabs)
17
+ slots(:block).each { render it }
18
+ end
19
+ end
20
+
21
+ def root_classes
22
+ super +
23
+ [
24
+ 'panel',
25
+ @modifier && "is-#{@modifier}"
26
+ ]
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Paragraph < Block
5
+ root_slot tag: :p, classes: ['block']
6
+ end
7
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Progress < BaseComponent
5
+ option :modifier, values: MODIFIERS, default: nil
6
+ option :size, values: %i[small normal medium large], default: :normal
7
+ option :value, default: 0
8
+ option :max, default: 100
9
+
10
+ root_slot tag: :progress
11
+
12
+ def view_template
13
+ super do
14
+ plain "#{@value}%"
15
+
16
+ yield if block_given?
17
+ end
18
+ end
19
+
20
+ def root_attributes
21
+ super.merge(
22
+ value: @value,
23
+ max: @max
24
+ )
25
+ end
26
+
27
+ def root_classes
28
+ super +
29
+ [
30
+ 'progress',
31
+ @size && "is-#{@size}",
32
+ @modifier && "is-#{@modifier}"
33
+ ]
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Radio < BaseComponent
5
+ option :disabled, values: BOOLEAN, default: false
6
+ option :checked, values: BOOLEAN, default: false
7
+
8
+ option :name
9
+ option :value
10
+
11
+ root_slot tag: :label, classes: ['radio']
12
+
13
+ def view_template
14
+ super do
15
+ render Input.new(**input_attributes)
16
+
17
+ yield if block_given?
18
+ end
19
+ end
20
+
21
+ def root_classes
22
+ super +
23
+ %w[
24
+ input
25
+ radio
26
+ ]
27
+ end
28
+
29
+ def root_attributes = super.merge(disabled: @disabled, checked: @checked)
30
+
31
+ def input_attributes = { type: 'radio', disabled: @disabled, name: @name, value: @value, checked: @checked }
32
+ end
33
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Section < BaseComponent
5
+ option :size, values: [nil, :medium, :large], default: nil
6
+ option :content, values: BOOLEAN, default: true
7
+ option :container, values: BOOLEAN, default: true
8
+ option :max_desktop, values: BOOLEAN, default: false
9
+
10
+ root_slot tag: :section
11
+ slot :section_content
12
+
13
+ def view_template(&)
14
+ super do
15
+ slot(:section_content, &)
16
+ end
17
+ end
18
+
19
+ def root_classes
20
+ super +
21
+ [
22
+ 'section',
23
+ @size && "is-#{@size}"
24
+ ]
25
+ end
26
+
27
+ def section_content_classes
28
+ [
29
+ @content && 'content',
30
+ @container && 'container',
31
+ @max_desktop && 'is-max-desktop'
32
+ ]
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ class Select < BaseInput
5
+ option :multiple, values: BOOLEAN, default: false
6
+ option :rows, default: nil
7
+ option :arrow, values: BOOLEAN, default: true
8
+ option :name
9
+ option :value
10
+
11
+ root_slot tag: :select
12
+
13
+ slots :option, component: 'Option'
14
+ slot :container, classes: ['select']
15
+
16
+ def view_template(&)
17
+ slot(:container) do
18
+ super do
19
+ slots(:option).each { render it }
20
+ end
21
+ end
22
+ end
23
+
24
+ def multiple(count)
25
+ @multiple = true
26
+ @rows = count
27
+
28
+ self
29
+ end
30
+
31
+ def root_classes
32
+ super + [
33
+ @multiple && 'is-multiple',
34
+ @arrow && 'is-link'
35
+ ]
36
+ end
37
+
38
+ def root_attributes
39
+ super.merge(multiple: @multiple, size: @rows, name: @name, value: @value)
40
+ end
41
+
42
+ class Option < BaseComponent
43
+ root_slot tag: :option
44
+
45
+ option :selected, values: BOOLEAN, default: false
46
+ option :value
47
+ option :label
48
+
49
+ def root_attributes
50
+ super.merge(
51
+ selected: @selected,
52
+ value: @value
53
+ )
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ module Shared
5
+ module AriaOptions
6
+ module ClassMethods
7
+ def aria_options
8
+ option :aria, default: {}
9
+ end
10
+ end
11
+
12
+ def self.included(base) = base.extend(ClassMethods)
13
+
14
+ def aria_attributes
15
+ @aria.transform_keys { |k| "aria-#{k}" }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ module Shared
5
+ module DataOptions
6
+ module ClassMethods
7
+ def data_options
8
+ option :data, default: {}
9
+ end
10
+ end
11
+
12
+ def self.included(base) = base.extend(ClassMethods)
13
+
14
+ def data_attributes
15
+ @data.transform_keys { |k| "data-#{k}" }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ module Shared
5
+ module FlexOptions
6
+ module ClassMethods
7
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
8
+ def flex_options
9
+ option :flex, values: self::BOOLEAN, default: false
10
+ option :flex_direction, values: [nil, :row, :row_reverse, :column, :column_reverse]
11
+ option :flex_wrap, values: [nil, :wrap, :nowrap, :wrap_reverse]
12
+ option :flex_justify_content,
13
+ values: [nil, :flex_start, :flex_end, :center, :space_between, :space_around, :space_evenly, :start,
14
+ :end, :left, :right]
15
+ option :flex_align_content,
16
+ values: [
17
+ nil,
18
+ :flex_start, :flex_end,
19
+ :center,
20
+ :space_between, :space_around, :space_evenly,
21
+ :stretch, :start, :end, :baseline
22
+ ]
23
+ option :flex_align_items,
24
+ values: [
25
+ nil,
26
+ :stretch, :flex_start, :flex_end, :center, :baseline, :start, :end, :self_start, :self_end
27
+ ]
28
+ option :flex_align_self,
29
+ values: [nil, :auto, :stretch, :flex_start, :flex_end, :center, :baseline]
30
+ option :flex_grow, values: (0..5).to_a.push(nil).freeze
31
+ option :flex_shrink, values: (0..5).to_a.push(nil).freeze
32
+ option :flex_gap, values: (1..8).to_a.push(nil).freeze
33
+ end
34
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
35
+ end
36
+
37
+ def self.included(base) = base.extend(ClassMethods)
38
+
39
+ # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
40
+ def flex_classes
41
+ [
42
+ @flex && 'is-flex',
43
+ @flex_direction && "is-flex-direction-#{css(@flex_direction)}",
44
+ @flex_wrap && "is-flex-#{css(@flex_wrap)}",
45
+ @flex_justify_content && "is-justify-content-#{css(@flex_justify_content)}",
46
+ @flex_align_content && "is-align-content-#{css(@flex_align_content)}",
47
+ @flex_align_items && "is-align-items-#{css(@flex_align_items)}",
48
+ @flex_align_self && "is-align-self-#{css(@flex_align_self)}",
49
+ @flex_grow && "is-flex-grow-#{css(@flex_grow)}",
50
+ @flex_shrink && "is-flex-shrink-#{css(@flex_shrink)}",
51
+ @flex_gap && "is-gap-#{css(@flex_gap)}"
52
+ ]
53
+ end
54
+ # rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BulmaX
4
+ module Shared
5
+ module GlobalOptions
6
+ module ClassMethods
7
+ def global_options
8
+ option :accesskey
9
+ option :draggable
10
+ option :hidden
11
+ option :id
12
+ option :lang
13
+ option :role
14
+ option :spellcheck
15
+ option :tabindex
16
+ option :title
17
+
18
+ option :fullwidth, values: [true, false], default: false
19
+ option :background_color, values: self::MODIFIERS_PALETTE, default: nil
20
+ option :extra_classes
21
+ end
22
+ end
23
+
24
+ def self.included(base) = base.extend(ClassMethods)
25
+
26
+ def global_attributes
27
+ {
28
+ accesskey: @accesskey,
29
+ draggable: @draggable,
30
+ hidden: @hidden,
31
+ id: @id,
32
+ lang: @lang,
33
+ role: @role,
34
+ spellcheck: @spellcheck,
35
+ tabindex: @tabindex,
36
+ title: @title
37
+ }
38
+ end
39
+
40
+ def global_classes
41
+ [
42
+ @fullwidth && 'is-fullwidth',
43
+ @background_color && "has-background-#{@background_color}",
44
+ *@extra_classes
45
+ ]
46
+ end
47
+ end
48
+ end
49
+ end