matestack-ui-bootstrap 1.4.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +17 -5
  3. data/README.md +53 -19
  4. data/lib/matestack/ui/bootstrap.rb +97 -17
  5. data/{app/concepts → lib}/matestack/ui/bootstrap/apps/admin_template.rb +14 -7
  6. data/lib/matestack/ui/bootstrap/base_component.rb +13 -0
  7. data/lib/matestack/ui/bootstrap/base_vue_js_component.rb +13 -0
  8. data/lib/matestack/ui/bootstrap/components/accordion.rb +58 -0
  9. data/{app/concepts → lib}/matestack/ui/bootstrap/components/alert.js +12 -9
  10. data/lib/matestack/ui/bootstrap/components/alert.rb +43 -0
  11. data/lib/matestack/ui/bootstrap/components/avatar.rb +27 -0
  12. data/lib/matestack/ui/bootstrap/components/badge.rb +32 -0
  13. data/lib/matestack/ui/bootstrap/components/breadcrumb.rb +50 -0
  14. data/lib/matestack/ui/bootstrap/components/button.rb +71 -0
  15. data/lib/matestack/ui/bootstrap/components/button_group.rb +36 -0
  16. data/lib/matestack/ui/bootstrap/components/card.rb +105 -0
  17. data/{app/concepts → lib}/matestack/ui/bootstrap/components/carousel.js +21 -18
  18. data/lib/matestack/ui/bootstrap/components/carousel.rb +103 -0
  19. data/{app/concepts → lib}/matestack/ui/bootstrap/components/close.rb +10 -9
  20. data/{app/concepts → lib}/matestack/ui/bootstrap/components/collapse.js +20 -17
  21. data/lib/matestack/ui/bootstrap/components/collapse.rb +54 -0
  22. data/{app/concepts → lib}/matestack/ui/bootstrap/components/dropdown.js +5 -2
  23. data/{app/concepts → lib}/matestack/ui/bootstrap/components/dropdown.rb +31 -26
  24. data/lib/matestack/ui/bootstrap/components/icon.rb +21 -0
  25. data/lib/matestack/ui/bootstrap/components/list_group.rb +148 -0
  26. data/{app/concepts → lib}/matestack/ui/bootstrap/components/modal.js +24 -21
  27. data/lib/matestack/ui/bootstrap/components/modal.rb +121 -0
  28. data/lib/matestack/ui/bootstrap/components/navbar.rb +163 -0
  29. data/{app/concepts → lib}/matestack/ui/bootstrap/components/page_heading.rb +7 -5
  30. data/{app/concepts → lib}/matestack/ui/bootstrap/components/pagination.rb +15 -13
  31. data/{app/concepts → lib}/matestack/ui/bootstrap/components/popover.js +4 -1
  32. data/{app/concepts → lib}/matestack/ui/bootstrap/components/popover.rb +26 -22
  33. data/{app/concepts → lib}/matestack/ui/bootstrap/components/progress.rb +24 -24
  34. data/lib/matestack/ui/bootstrap/components/scrollspy.rb +50 -0
  35. data/lib/matestack/ui/bootstrap/components/section_card.rb +33 -0
  36. data/lib/matestack/ui/bootstrap/components/spinner.rb +35 -0
  37. data/lib/matestack/ui/bootstrap/components/tab_nav.rb +79 -0
  38. data/lib/matestack/ui/bootstrap/components/tab_nav_content.rb +35 -0
  39. data/{app/concepts → lib}/matestack/ui/bootstrap/components/toast.js +27 -18
  40. data/lib/matestack/ui/bootstrap/components/toast.rb +113 -0
  41. data/{app/concepts → lib}/matestack/ui/bootstrap/components/tooltip.js +4 -1
  42. data/lib/matestack/ui/bootstrap/components/tooltip.rb +66 -0
  43. data/{app/concepts → lib}/matestack/ui/bootstrap/content/figure.rb +4 -2
  44. data/lib/matestack/ui/bootstrap/content/smart_collection/collection.rb +120 -0
  45. data/{app/concepts/matestack/ui/bootstrap/content/collection → lib/matestack/ui/bootstrap/content/smart_collection}/collection.scss +0 -0
  46. data/lib/matestack/ui/bootstrap/content/smart_collection/content.rb +118 -0
  47. data/{app/concepts/matestack/ui/bootstrap/content/collection → lib/matestack/ui/bootstrap/content/smart_collection}/filter.rb +7 -3
  48. data/{app/concepts/matestack/ui/bootstrap/content/collection → lib/matestack/ui/bootstrap/content/smart_collection}/paginate.rb +19 -14
  49. data/lib/matestack/ui/bootstrap/form/checkbox.rb +90 -0
  50. data/lib/matestack/ui/bootstrap/form/input.rb +118 -0
  51. data/lib/matestack/ui/bootstrap/form/radio.rb +57 -0
  52. data/lib/matestack/ui/bootstrap/form/select.rb +63 -0
  53. data/lib/matestack/ui/bootstrap/form/submit.rb +20 -0
  54. data/lib/matestack/ui/bootstrap/form/switch.rb +32 -0
  55. data/lib/matestack/ui/bootstrap/form/textarea.rb +49 -0
  56. data/lib/matestack/ui/bootstrap/index.js +24 -0
  57. data/lib/matestack/ui/bootstrap/layout/column.rb +49 -0
  58. data/{app/concepts → lib}/matestack/ui/bootstrap/layout/container.rb +12 -9
  59. data/lib/matestack/ui/bootstrap/layout/row.rb +25 -0
  60. data/{app/concepts → lib}/matestack/ui/bootstrap/layout/sidebar.js +5 -2
  61. data/{app/concepts → lib}/matestack/ui/bootstrap/layout/sidebar.rb +10 -10
  62. data/{app/concepts → lib}/matestack/ui/bootstrap/layout/sidebar.scss +0 -0
  63. data/lib/matestack/ui/bootstrap/registry.rb +173 -0
  64. data/{app/javascript/matestack-ui-bootstrap → lib/matestack/ui/bootstrap}/stylesheets/matestack-ui-bootstrap.scss +0 -0
  65. data/lib/matestack/ui/bootstrap/version.rb +1 -1
  66. data/lib/tasks/matestack/ui/bootstrap_tasks.rake +25 -25
  67. metadata +68 -76
  68. data/app/assets/images/avatar-placeholder.png +0 -0
  69. data/app/assets/images/icons/bootstrap-icons.svg +0 -1
  70. data/app/concepts/matestack/ui/bootstrap/components/accordion.rb +0 -53
  71. data/app/concepts/matestack/ui/bootstrap/components/alert.rb +0 -34
  72. data/app/concepts/matestack/ui/bootstrap/components/avatar.rb +0 -27
  73. data/app/concepts/matestack/ui/bootstrap/components/badge.rb +0 -30
  74. data/app/concepts/matestack/ui/bootstrap/components/breadcrumb.rb +0 -46
  75. data/app/concepts/matestack/ui/bootstrap/components/button.rb +0 -54
  76. data/app/concepts/matestack/ui/bootstrap/components/button_group.rb +0 -36
  77. data/app/concepts/matestack/ui/bootstrap/components/card.rb +0 -100
  78. data/app/concepts/matestack/ui/bootstrap/components/carousel.rb +0 -85
  79. data/app/concepts/matestack/ui/bootstrap/components/chart.js +0 -232
  80. data/app/concepts/matestack/ui/bootstrap/components/chart.rb +0 -71
  81. data/app/concepts/matestack/ui/bootstrap/components/collapse.rb +0 -43
  82. data/app/concepts/matestack/ui/bootstrap/components/icon.rb +0 -19
  83. data/app/concepts/matestack/ui/bootstrap/components/list_group.rb +0 -83
  84. data/app/concepts/matestack/ui/bootstrap/components/modal.rb +0 -106
  85. data/app/concepts/matestack/ui/bootstrap/components/navbar.rb +0 -120
  86. data/app/concepts/matestack/ui/bootstrap/components/scrollspy.rb +0 -33
  87. data/app/concepts/matestack/ui/bootstrap/components/section_card.rb +0 -31
  88. data/app/concepts/matestack/ui/bootstrap/components/spinner.rb +0 -31
  89. data/app/concepts/matestack/ui/bootstrap/components/tab_nav.rb +0 -81
  90. data/app/concepts/matestack/ui/bootstrap/components/tab_nav_content.rb +0 -32
  91. data/app/concepts/matestack/ui/bootstrap/components/toast.rb +0 -99
  92. data/app/concepts/matestack/ui/bootstrap/components/tooltip.rb +0 -82
  93. data/app/concepts/matestack/ui/bootstrap/content/collection/collection.rb +0 -112
  94. data/app/concepts/matestack/ui/bootstrap/content/collection/content.rb +0 -101
  95. data/app/concepts/matestack/ui/bootstrap/form/checkbox.rb +0 -90
  96. data/app/concepts/matestack/ui/bootstrap/form/date.js +0 -38
  97. data/app/concepts/matestack/ui/bootstrap/form/date.rb +0 -98
  98. data/app/concepts/matestack/ui/bootstrap/form/input.rb +0 -123
  99. data/app/concepts/matestack/ui/bootstrap/form/radio.rb +0 -65
  100. data/app/concepts/matestack/ui/bootstrap/form/select.haml +0 -11
  101. data/app/concepts/matestack/ui/bootstrap/form/select.rb +0 -74
  102. data/app/concepts/matestack/ui/bootstrap/form/submit.rb +0 -20
  103. data/app/concepts/matestack/ui/bootstrap/form/switch.rb +0 -90
  104. data/app/concepts/matestack/ui/bootstrap/layout/column.rb +0 -47
  105. data/app/concepts/matestack/ui/bootstrap/layout/row.rb +0 -15
  106. data/app/concepts/matestack/ui/bootstrap/pages/devise/sign_in.rb +0 -40
  107. data/app/concepts/matestack/ui/bootstrap/registry.rb +0 -63
  108. data/app/helpers/matestack/ui/bootstrap/application_helper.rb +0 -13
  109. data/app/javascript/matestack-ui-bootstrap/index.js +0 -26
  110. data/app/javascript/packs/matestack-ui-bootstrap.js +0 -2
  111. data/config/routes.rb +0 -2
  112. data/lib/matestack/ui/bootstrap/engine.rb +0 -26
@@ -0,0 +1,27 @@
1
+ class Matestack::Ui::Bootstrap::Components::Avatar < Matestack::Ui::Bootstrap::BaseComponent
2
+
3
+ optional :bg_variant, :text_variant, :img_path, :size, class: { as: :bs_class }
4
+
5
+ def response
6
+ if context.text.present? && context.img_path.nil?
7
+ div class: "rounded-circle bg-#{context.bg_variant || 'primary'} text-#{context.text_variant || 'white'} text-center p-2 #{context.bs_class}",
8
+ style: "height: #{height}px; width: #{width}px; display: inline-block;" do
9
+ plain context.text
10
+ end
11
+ else
12
+ div class: "rounded-circle text-#{context.text_variant || 'white'} text-center p-2 #{context.bs_class}",
13
+ style: "height: #{height}px; width: #{width}px; display: inline-block; background-image: url(#{context.img_path}); background-size: contain;" do
14
+ plain context.text
15
+ end
16
+ end
17
+ end
18
+
19
+ def height
20
+ context.size || 40
21
+ end
22
+
23
+ def width
24
+ context.size || 40
25
+ end
26
+
27
+ end
@@ -0,0 +1,32 @@
1
+ require_relative "../base_component"
2
+
3
+ class Matestack::Ui::Bootstrap::Components::Badge < Matestack::Ui::Bootstrap::BaseComponent
4
+
5
+ optional class: { as: :bs_class }
6
+ optional :variant, :rounded, :visually_hidden
7
+
8
+ def response
9
+ span badge_attributes do
10
+ plain context.text if context.text
11
+ yield if block_given?
12
+ end
13
+ span context.visually_hidden, class: "visually-hidden" if context.visually_hidden.present?
14
+ end
15
+
16
+ protected
17
+
18
+ def badge_attributes
19
+ options.merge(
20
+ class: badge_classes
21
+ )
22
+ end
23
+
24
+ def badge_classes
25
+ [].tap do |classes|
26
+ classes << 'badge'
27
+ classes << (context.variant.present? ? "bg-#{context.variant}" : "bg-secondary")
28
+ classes << "rounded-pill" if context.rounded
29
+ classes << context.bs_class
30
+ end.join(' ').strip
31
+ end
32
+ end
@@ -0,0 +1,50 @@
1
+ require_relative "../base_component"
2
+
3
+ class Matestack::Ui::Bootstrap::Components::Breadcrumb < Matestack::Ui::Bootstrap::BaseComponent
4
+
5
+ optional :items # list of items with path and text
6
+ optional class: { as: :bs_class } # adding custom class to breadcrumb list
7
+ optional :nav_class
8
+
9
+ def response
10
+ nav class: context.nav_class, "aria-label": "breadcrumb" do
11
+ ol breadcrumb_attributes do
12
+ context.items&.each_with_index do |item, index|
13
+ li link_attrs((context.items.size - 1) == index) do
14
+ case item[:type]
15
+ when :link
16
+ a item
17
+ when :transition
18
+ transition item
19
+ else
20
+ plain item[:text]
21
+ end
22
+ end
23
+ end
24
+ yield if block_given?
25
+ end
26
+ end
27
+ end
28
+
29
+ protected
30
+
31
+ def link_attrs(last = false)
32
+ {}.tap do |hash|
33
+ hash[:class] = "breadcrumb-item #{'active' if last}"
34
+ hash[:"aria-current"] = "page" if last
35
+ end
36
+ end
37
+
38
+ def breadcrumb_attributes
39
+ options.merge(
40
+ class: breadcrumb_classes
41
+ )
42
+ end
43
+
44
+ def breadcrumb_classes
45
+ [].tap do |classes|
46
+ classes << "breadcrumb"
47
+ classes << context.bs_class
48
+ end.join(' ').strip
49
+ end
50
+ end
@@ -0,0 +1,71 @@
1
+ require_relative "../base_component"
2
+
3
+ class Matestack::Ui::Bootstrap::Components::Button < Matestack::Ui::Bootstrap::BaseComponent
4
+
5
+ optional :type, :variant, :size, :outline
6
+ optional :attributes, class: { as: :bs_class }
7
+ optional :transition
8
+ optional :action
9
+ optional :onclick
10
+ optional :link
11
+
12
+ def response(&block)
13
+ if context.transition.present? && context.transition.is_a?(Hash)
14
+ transition button_attributes.merge(context.transition.merge({role: "button"})) do
15
+ inner_response(&block)
16
+ end
17
+ elsif context.action.present? && context.action.is_a?(Hash)
18
+ action button_attributes.merge(context.action.merge({role: "button"})) do
19
+ inner_response(&block)
20
+ end
21
+ elsif context.onclick.present? && context.onclick.is_a?(Hash)
22
+ onclick button_attributes.merge(context.onclick.merge({role: "button"})) do
23
+ inner_response(&block)
24
+ end
25
+ elsif context.link.present? && context.link.is_a?(Hash)
26
+ a button_attributes.merge(context.link.merge({role: "button"})) do
27
+ inner_response(&block)
28
+ end
29
+ else
30
+ button_response(&block)
31
+ end
32
+ end
33
+
34
+ def button_response(&block)
35
+ button button_attributes do
36
+ inner_response(&block)
37
+ end
38
+ end
39
+
40
+ def inner_response(&block)
41
+ plain context.text if context.text
42
+ yield if block_given?
43
+ end
44
+
45
+ protected
46
+
47
+ def button_attributes
48
+ options.tap do |opts|
49
+ opts[:type] = context.type || 'button'
50
+ opts[:class] = button_classes
51
+ opts.merge(context.attributes || {})
52
+ end
53
+ end
54
+
55
+ def button_classes
56
+ [].tap do |classes|
57
+ classes << 'btn'
58
+ # btn variants outlined or solid background
59
+ if context.outline
60
+ classes << "btn-outline-#{context.variant.to_s.gsub('_', '-') || 'primary'}"
61
+ else
62
+ classes << (context.variant ? "btn-#{context.variant.to_s.gsub('_', '-')}" : 'btn-primary')
63
+ end
64
+ # btn size
65
+ classes << "btn-#{context.size}" if context.size
66
+ # custom classes
67
+ classes << context.bs_class
68
+ end.join(' ').strip
69
+ end
70
+
71
+ end
@@ -0,0 +1,36 @@
1
+ require_relative "../base_component"
2
+
3
+ class Matestack::Ui::Bootstrap::Components::ButtonGroup < Matestack::Ui::Bootstrap::BaseComponent
4
+
5
+ optional class: { as: :bs_class }
6
+ optional :label
7
+ optional :toolbar, :size, :vertical
8
+
9
+ def response
10
+ div buttongroup_attributes do
11
+ yield if block_given?
12
+ end
13
+ end
14
+
15
+ protected
16
+
17
+ def buttongroup_attributes
18
+ attributes = {}.tap do |hash|
19
+ hash[:class] = buttongroup_classes
20
+ hash[:role] = "#{context.toolbar ? :toolbar : :group}"
21
+ hash[:"aria-label"] = context.label
22
+ end
23
+ options.merge(
24
+ attributes
25
+ )
26
+ end
27
+
28
+ def buttongroup_classes
29
+ [].tap do |classes|
30
+ classes << ("btn-#{context.toolbar ? :toolbar : :group}#{'-vertical' if context.vertical}")
31
+ classes << "btn-group-#{context.size}" if context.size.present?
32
+ classes << context.bs_class
33
+ end.join(' ').strip
34
+ end
35
+
36
+ end
@@ -0,0 +1,105 @@
1
+ require_relative "../base_component"
2
+
3
+ class Matestack::Ui::Bootstrap::Components::Card < Matestack::Ui::Bootstrap::BaseComponent
4
+
5
+ optional class: { as: :bs_class }
6
+
7
+ # header attributes, expects a hash or string
8
+ # possible keys `:class, :text`
9
+ optional :header
10
+ # footer attributes, expects a hash or string
11
+ # possible keys `:class, :text`
12
+ optional :footer
13
+
14
+ optional :title, :body, :subtitle # body attributes
15
+ optional :img_path, :img_pos, :alt_text # image attributes
16
+
17
+ optional :content_wrapper_class # class for content wrapper -> useful for content padding without affecting top image
18
+
19
+ def response
20
+ div card_attributes do
21
+ if context.header || slots && slots[:header]
22
+ header_partial
23
+ end
24
+
25
+ img_partial :top unless context.img_pos == :bottom
26
+ div class: context.content_wrapper_class do
27
+ body_partial if context.title || context.body || slots && slots[:body]
28
+
29
+ # custom body components
30
+ # needed a div otherwise it will be displayed below footer
31
+ div class: "p-3 pt-1" do yield if block_given? end
32
+
33
+ img_partial :bottom if context.img_pos == :bottom
34
+
35
+ footer_partial if context.footer || slots && slots[:footer]
36
+ end
37
+ end
38
+ end
39
+
40
+ protected
41
+
42
+ def header_partial
43
+ header = self.context.header.is_a?(Hash) ? self.context.header : { text: self.context.header }
44
+ div class: "card-header #{header[:class]}" do
45
+ plain header[:text] if header[:text].present?
46
+ slot :header if slots && slots[:header]
47
+ end
48
+ end
49
+
50
+ def body_partial
51
+ div class: "card-body" do
52
+ # title
53
+ card_title(context.title, "card-title")
54
+ # subtitle
55
+ card_title(context.subtitle, 6, "card-subtitle text-muted")
56
+ # body
57
+ if context.body.is_a? Hash
58
+ paragraph class: "card-text #{body[:class]}" do
59
+ plain context.body[:text]
60
+ end
61
+ elsif context.body
62
+ paragraph class: "card-text" do
63
+ plain context.body
64
+ end
65
+ end
66
+ slot :body if slots && slots[:body]
67
+ end
68
+ end
69
+
70
+ def footer_partial
71
+ footer = self.context.footer.is_a?(Hash) ? self.context.footer : { text: self.context.footer }
72
+ div class: "card-footer #{footer[:class]}" do
73
+ plain footer[:text] if footer[:text].present?
74
+ slot :footer if slots && slots[:footer]
75
+ end
76
+ end
77
+
78
+ def img_partial pos
79
+ img class: "card-img-#{pos}", path: context.img_path, alt: context.alt_text if context.img_path.present?
80
+ end
81
+
82
+ def card_attributes
83
+ options.merge(
84
+ class: card_classes
85
+ )
86
+ end
87
+
88
+ def card_classes
89
+ [].tap do |classes|
90
+ classes << 'card'
91
+ classes << context.bs_class
92
+ end.join(' ').strip
93
+ end
94
+
95
+ def card_title(options, default_size = 5, title_class)
96
+ if options.is_a? Hash
97
+ heading context.text, size: (context.size || default_size), class: "#{context.bs_class} #{title_class}"
98
+ elsif options
99
+ heading size: default_size, class: title_class do
100
+ plain options
101
+ end
102
+ end
103
+ end
104
+
105
+ end
@@ -1,6 +1,9 @@
1
1
  import * as bootstrap from 'bootstrap'
2
+ import Vue from 'vue/dist/vue.esm'
2
3
 
3
- MatestackUiCore.Vue.component('matestack-ui-bootstrap-carousel', {
4
+ import MatestackUiCore from 'matestack-ui-core'
5
+
6
+ Vue.component('matestack-ui-bootstrap-carousel', {
4
7
  mixins: [MatestackUiCore.componentMixin],
5
8
  data() {
6
9
  return {
@@ -31,48 +34,48 @@ MatestackUiCore.Vue.component('matestack-ui-bootstrap-carousel', {
31
34
  const self = this;
32
35
  var myCarousel = self.$el;
33
36
  self.carouselInstance = new bootstrap.Carousel(myCarousel, {
34
- interval: (self.componentConfig['interval'] || 5000)
37
+ interval: (self.props['interval'] || 5000)
35
38
  })
36
39
  },
37
40
 
38
41
  created: function() {
39
42
  const self = this
40
- if(self.componentConfig["cycle_on"] != undefined){
41
- var cycle_events = self.componentConfig["cycle_on"].split(",")
43
+ if(self.props["cycle_on"] != undefined){
44
+ var cycle_events = self.props["cycle_on"].split(",")
42
45
  cycle_events.forEach(cycle_event => MatestackUiCore.matestackEventHub.$on(cycle_event.trim(), self.cycle));
43
46
  }
44
- if(self.componentConfig["pause_on"] != undefined){
45
- var pause_events = self.componentConfig["pause_on"].split(",")
47
+ if(self.props["pause_on"] != undefined){
48
+ var pause_events = self.props["pause_on"].split(",")
46
49
  pause_events.forEach(pause_event => MatestackUiCore.matestackEventHub.$on(pause_event.trim(), self.pause));
47
50
  }
48
- if(self.componentConfig["prev_on"] != undefined){
49
- var prev_events = self.componentConfig["prev_on"].split(",")
51
+ if(self.props["prev_on"] != undefined){
52
+ var prev_events = self.props["prev_on"].split(",")
50
53
  prev_events.forEach(prev_event => MatestackUiCore.matestackEventHub.$on(prev_event.trim(), self.prev));
51
54
  }
52
- if(self.componentConfig["next_on"] != undefined){
53
- var next_events = self.componentConfig["next_on"].split(",")
55
+ if(self.props["next_on"] != undefined){
56
+ var next_events = self.props["next_on"].split(",")
54
57
  next_events.forEach(next_event => MatestackUiCore.matestackEventHub.$on(next_event.trim(), self.next));
55
58
  }
56
59
  },
57
60
 
58
61
  beforeDestroy: function() {
59
62
  const self = this
60
- if(self.componentConfig["cycle_on"] != undefined){
61
- var cycle_events = self.componentConfig["cycle_on"].split(",")
63
+ if(self.props["cycle_on"] != undefined){
64
+ var cycle_events = self.props["cycle_on"].split(",")
62
65
  cycle_events.forEach(cycle_event => MatestackUiCore.matestackEventHub.$off(cycle_event.trim(), self.cycle));
63
66
  }
64
67
 
65
- if(self.componentConfig["pause_on"] != undefined){
66
- var pause_events = self.componentConfig["pause_on"].split(",")
68
+ if(self.props["pause_on"] != undefined){
69
+ var pause_events = self.props["pause_on"].split(",")
67
70
  pause_events.forEach(pause_event => MatestackUiCore.matestackEventHub.$off(pause_event.trim(), self.pause));
68
71
  }
69
72
 
70
- if(self.componentConfig["prev_on"] != undefined){
71
- var prev_events = self.componentConfig["prev_on"].split(",")
73
+ if(self.props["prev_on"] != undefined){
74
+ var prev_events = self.props["prev_on"].split(",")
72
75
  prev_events.forEach(prev_event => MatestackUiCore.matestackEventHub.$off(prev_event.trim(), self.prev));
73
76
  }
74
- if(self.componentConfig["next_on"] != undefined){
75
- var next_events = self.componentConfig["next_on"].split(",")
77
+ if(self.props["next_on"] != undefined){
78
+ var next_events = self.props["next_on"].split(",")
76
79
  next_events.forEach(next_event => MatestackUiCore.matestackEventHub.$off(next_event.trim(), self.next));
77
80
  }
78
81
  },
@@ -0,0 +1,103 @@
1
+ require_relative "../base_vue_js_component"
2
+
3
+ class Matestack::Ui::Bootstrap::Components::Carousel < Matestack::Ui::Bootstrap::BaseVueJsComponent
4
+ vue_name "matestack-ui-bootstrap-carousel"
5
+
6
+ optional :start, :controls, :indicators, :fade, :interval, :variant
7
+ optional :items, class: { as: :bs_class }
8
+ # possible keys for items: path, title, text, interval
9
+ # event trigger
10
+ optional :cycle_on, :pause_on, :prev_on, :next_on
11
+
12
+ def response
13
+ div carousel_attributes do
14
+ # carousel indicator
15
+ indicator_partial if context.indicators.present?
16
+ # carousel content
17
+ div class: "carousel-inner" do
18
+ yield if block_given?
19
+ carousel_partial if context.items
20
+ end
21
+ controls_partial if context.controls
22
+ end
23
+ end
24
+
25
+ protected
26
+
27
+ def vue_props
28
+ {}.tap do |props|
29
+ props["carousel-id"] = carousel_id
30
+ props[:interval] = context.interval
31
+ props[:cycle_on] = context.cycle_on
32
+ props[:pause_on] = context.pause_on
33
+ props[:prev_on] = context.prev_on
34
+ props[:next_on] = context.next_on
35
+ end
36
+ end
37
+
38
+ def indicator_partial
39
+ ol class: "carousel-indicators" do
40
+ context.items.size.times do |index|
41
+ li data: { "bs-target": "##{carousel_id}", 'bs-slide-to': index },
42
+ class: "#{'active' if index == (context.start || 0) }"
43
+ end
44
+ end
45
+ end
46
+
47
+ def carousel_partial
48
+ context.items.each_with_index do |item, index|
49
+ div class: "carousel-item #{'active' if index == (context.start || 0) } #{item[:class]}".strip,
50
+ data: { "bs-interval": item[:interval] } do
51
+ img class: "d-block w-100", path: item[:path]
52
+ if item[:title] || item[:text]
53
+ div class: "carousel-caption d-none d-md-block #{item[:title_class]}" do
54
+ heading size: 5 do
55
+ plain item[:title]
56
+ end
57
+ paragraph do
58
+ plain item[:text]
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ def controls_partial
67
+ a class: "carousel-control-prev", data: { "bs-target": "##{carousel_id}", "bs-slide": :prev }, 'role': "button" do
68
+ span class: "carousel-control-prev-icon", 'aria-hidden': "true"
69
+ span class: "visually-hidden" do
70
+ plain "Previous"
71
+ end
72
+ end
73
+ a class: "carousel-control-next", data: { "bs-target": "##{carousel_id}", "bs-slide": :next }, 'role': "button" do
74
+ span class: "carousel-control-next-icon", 'aria-hidden': "true"
75
+ span class: "visually-hidden" do
76
+ plain "Next"
77
+ end
78
+ end
79
+ end
80
+
81
+ def carousel_attributes
82
+ options.merge(
83
+ id: carousel_id,
84
+ class: carousel_classes,
85
+ data: { "bs-ride": 'carousel', "bs-interval": (context.interval || 5000) }
86
+ )
87
+ end
88
+
89
+ def carousel_classes
90
+ [].tap do |classes|
91
+ classes << 'carousel slide'
92
+ classes << 'carousel-fade' if context.fade
93
+ classes << 'carousel-dark' if context.variant == :dark
94
+ #custom classes
95
+ classes << context.bs_class
96
+ end.join(' ').strip
97
+ end
98
+
99
+ def carousel_id
100
+ @carousel_id ||= "matestack-carousel-#{SecureRandom.hex}"
101
+ end
102
+
103
+ end