loco_motion-rails 0.0.6

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 (67) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +880 -0
  4. data/app/components/daisy/actions/button_component.html.haml +7 -0
  5. data/app/components/daisy/actions/button_component.rb +52 -0
  6. data/app/components/daisy/actions/dropdown_component.html.haml +13 -0
  7. data/app/components/daisy/actions/dropdown_component.rb +48 -0
  8. data/app/components/daisy/actions/modal_component.html.haml +31 -0
  9. data/app/components/daisy/actions/modal_component.rb +92 -0
  10. data/app/components/daisy/actions/swap_component.html.haml +17 -0
  11. data/app/components/daisy/actions/swap_component.rb +56 -0
  12. data/app/components/daisy/actions/theme_controller_component.html.haml +5 -0
  13. data/app/components/daisy/actions/theme_controller_component.rb +8 -0
  14. data/app/components/daisy/data_display/accordion_component.html.haml +4 -0
  15. data/app/components/daisy/data_display/accordion_component.rb +82 -0
  16. data/app/components/daisy/data_display/avatar_component.html.haml +9 -0
  17. data/app/components/daisy/data_display/avatar_component.rb +60 -0
  18. data/app/components/daisy/data_display/badge_component.html.haml +2 -0
  19. data/app/components/daisy/data_display/badge_component.rb +27 -0
  20. data/app/components/daisy/data_display/card_component.html.haml +17 -0
  21. data/app/components/daisy/data_display/card_component.rb +53 -0
  22. data/app/components/daisy/data_display/carousel_component.html.haml +3 -0
  23. data/app/components/daisy/data_display/carousel_component.rb +17 -0
  24. data/app/components/daisy/data_display/chat_component.html.haml +14 -0
  25. data/app/components/daisy/data_display/chat_component.rb +38 -0
  26. data/app/components/daisy/data_display/collapse_component.html.haml +13 -0
  27. data/app/components/daisy/data_display/collapse_component.rb +37 -0
  28. data/app/components/daisy/data_display/countdown_component.html.haml +24 -0
  29. data/app/components/daisy/data_display/countdown_component.rb +70 -0
  30. data/app/components/daisy/data_display/countdown_controller.js +78 -0
  31. data/app/components/daisy/data_display/diff_component.html.haml +6 -0
  32. data/app/components/daisy/data_display/diff_component.rb +25 -0
  33. data/app/components/daisy/data_display/kbd_component.html.haml +2 -0
  34. data/app/components/daisy/data_display/kbd_component.rb +21 -0
  35. data/app/components/daisy/data_display/stat_component.html.haml +27 -0
  36. data/app/components/daisy/data_display/stat_component.rb +41 -0
  37. data/app/components/daisy/data_display/table_component.html.haml +14 -0
  38. data/app/components/daisy/data_display/table_component.rb +148 -0
  39. data/app/components/daisy/data_display/timeline_component.html.haml +7 -0
  40. data/app/components/daisy/data_display/timeline_component.rb +8 -0
  41. data/app/components/daisy/data_display/timeline_event_component.html.haml +28 -0
  42. data/app/components/daisy/data_display/timeline_event_component.rb +47 -0
  43. data/app/components/daisy/feedback/alert_component.html.haml +8 -0
  44. data/app/components/daisy/feedback/alert_component.rb +19 -0
  45. data/app/components/daisy/layout/join_component.rb +15 -0
  46. data/app/components/daisy/navigation/bottom_nav_component.rb +59 -0
  47. data/app/components/daisy/navigation/breadcrumbs_component.html.haml +7 -0
  48. data/app/components/daisy/navigation/breadcrumbs_component.rb +15 -0
  49. data/app/components/daisy/navigation/link_component.html.haml +4 -0
  50. data/app/components/daisy/navigation/link_component.rb +34 -0
  51. data/app/components/daisy/navigation/menu_component.html.haml +3 -0
  52. data/app/components/daisy/navigation/menu_component.rb +49 -0
  53. data/app/components/daisy/navigation/navbar_component.html.haml +4 -0
  54. data/app/components/daisy/navigation/navbar_component.rb +12 -0
  55. data/app/components/daisy/navigation/steps_component.rb +40 -0
  56. data/app/components/daisy/navigation/tabs_component.html.haml +4 -0
  57. data/app/components/daisy/navigation/tabs_component.rb +107 -0
  58. data/app/components/hero/icon_component.rb +18 -0
  59. data/lib/daisy/helpers.rb +61 -0
  60. data/lib/daisy.rb +19 -0
  61. data/lib/loco_motion/base_component.rb +371 -0
  62. data/lib/loco_motion/basic_component.rb +18 -0
  63. data/lib/loco_motion/component_config.rb +165 -0
  64. data/lib/loco_motion/engine.rb +8 -0
  65. data/lib/loco_motion/errors.rb +33 -0
  66. data/lib/loco_motion.rb +48 -0
  67. metadata +408 -0
@@ -0,0 +1,7 @@
1
+ = part(:component) do
2
+ - if content?
3
+ = content
4
+ - else
5
+ = heroicon_tag(@left_icon, **left_icon_html) if @left_icon
6
+ = @simple_title if @simple_title
7
+ = heroicon_tag(@right_icon, **right_icon_html) if @right_icon
@@ -0,0 +1,52 @@
1
+ # Here are the Button docs!
2
+ class Daisy::Actions::ButtonComponent < LocoMotion.configuration.base_component_class
3
+ set_component_name :btn
4
+
5
+ def initialize(*args, **kws, &block)
6
+ super
7
+
8
+ @href = config_option(:href)
9
+ @target = config_option(:target)
10
+
11
+ @icon = config_option(:icon)
12
+ @icon_css = config_option(:icon_css, "[:where(&)]:size-5")
13
+ @icon_html = config_option(:icon_html, {})
14
+
15
+ @left_icon = config_option(:left_icon, @icon)
16
+ @left_icon_css = config_option(:left_icon_css, @icon_css)
17
+ @left_icon_html = config_option(:left_icon_html, @icon_html)
18
+
19
+ @right_icon = config_option(:right_icon)
20
+ @right_icon_css = config_option(:right_icon_css, @icon_css)
21
+ @right_icon_html = config_option(:right_icon_html, @icon_html)
22
+
23
+ @simple_title = config_option(:title, @left_icon || @right_icon ? nil : "Submit")
24
+ end
25
+
26
+ def before_render
27
+ setup_component
28
+ end
29
+
30
+ private
31
+
32
+ def setup_component
33
+ if @href
34
+ set_tag_name(:component, :a)
35
+ add_html(:component, { href: @href, target: @target })
36
+ else
37
+ set_tag_name(:component, :button)
38
+ end
39
+
40
+ add_css(:component, "btn")
41
+
42
+ add_css(:component, "items-center gap-2") if @icon
43
+ end
44
+
45
+ def left_icon_html
46
+ { class: @left_icon_css }.merge(@left_icon_html)
47
+ end
48
+
49
+ def right_icon_html
50
+ { class: @right_icon_css }.merge(@right_icon_html)
51
+ end
52
+ end
@@ -0,0 +1,13 @@
1
+ = part(:component) do
2
+ - if title?
3
+ = title
4
+ - else
5
+ = part(:title) do
6
+ = @simple_title
7
+
8
+ - if items.any?
9
+ = part(:menu) do
10
+ - items.each do |item|
11
+ = item
12
+ - else
13
+ = content
@@ -0,0 +1,48 @@
1
+ # Here are the Button docs!
2
+ class Daisy::Actions::DropdownComponent < LocoMotion.configuration.base_component_class
3
+
4
+ TitleComponent = LocoMotion::BasicComponent.build do
5
+ def before_render
6
+ add_html(:component, { role: "button", tabindex: 0 })
7
+ end
8
+ end
9
+
10
+ ItemComponent = LocoMotion::BasicComponent.build do
11
+ def before_render
12
+ set_tag_name(:component, :li)
13
+ end
14
+ end
15
+
16
+ define_parts :title, :menu
17
+
18
+ renders_one :title, TitleComponent
19
+ renders_many :items, ItemComponent
20
+
21
+ def initialize(*args, **kws, &block)
22
+ super
23
+
24
+ @simple_title = config_option(:title, "Submit")
25
+ end
26
+
27
+ def before_render
28
+ setup_component
29
+ setup_title
30
+ setup_menu
31
+ end
32
+
33
+ def setup_component
34
+ add_css(:component, "dropdown")
35
+ end
36
+
37
+ def setup_title
38
+ set_tag_name(:title, :div)
39
+ add_css(:title, "btn")
40
+ add_html(:title, { role: "button", tabindex: 0 })
41
+ end
42
+
43
+ def setup_menu
44
+ set_tag_name(:menu, :ul)
45
+ add_css(:menu, "dropdown-content menu bg-base-100 rounded-box shadow w-52 p-2 z-[1]")
46
+ add_html(:menu, { role: "menu", tabindex: 0 })
47
+ end
48
+ end
@@ -0,0 +1,31 @@
1
+ - if activator?
2
+ = part(:activator) do
3
+ = activator
4
+
5
+ = part(:component) do
6
+ = part(:box) do
7
+ - if closable?
8
+ = part(:close_icon_wrapper) do
9
+ = part(:close_icon) do
10
+ - if close_icon?
11
+ = close_icon
12
+ - else
13
+ = heroicon_tag "x-mark"
14
+
15
+ - if title?
16
+ = title
17
+ - elsif @simple_title.present?
18
+ = part(:title) do
19
+ = @simple_title
20
+
21
+ = content
22
+
23
+ = part(:actions) do
24
+ = part(:start_actions) do
25
+ - if start_actions?
26
+ = start_actions
27
+ = part(:end_actions) do
28
+ - if end_actions?
29
+ = end_actions
30
+ = part(:backdrop) do
31
+ %button close
@@ -0,0 +1,92 @@
1
+ # This is a Modal component.
2
+ # @!parse class Daisy::Actions::ModalComponent < LocoMotion::BaseComponent; end
3
+ class Daisy::Actions::ModalComponent < LocoMotion.configuration.base_component_class
4
+ set_component_name :modal
5
+
6
+ define_parts :dialog, :box, :actions,
7
+ :activator, :close_icon_wrapper, :close_icon,
8
+ :backdrop,
9
+ :title, :start_actions, :end_actions
10
+
11
+ renders_one :activator
12
+ renders_one :close_icon
13
+ renders_one :title
14
+ renders_one :start_actions
15
+ renders_one :end_actions
16
+
17
+ # @return [Boolean] Whether or not this dialog can be closed.
18
+ attr_reader :closable
19
+ alias :closable? :closable
20
+
21
+ # @return [String] The unique ID for the `<dialog>` element.
22
+ attr_reader :dialog_id
23
+
24
+ # @return [String] Accessor for the `title` string passed via the component
25
+ # config.
26
+ attr_reader :simple_title
27
+
28
+ #
29
+ # Instantiate a new Modal component. All options are expected to be passed as
30
+ # keyword arguments.
31
+ #
32
+ # @overload initialize(dialog_id: nil, closable: true, title: nil)
33
+ # @param dialog_id [String] A specific ID you would like the dialog to use.
34
+ # Auto-generates a random ID using `SecureRandom.uuid` if not provided.
35
+ #
36
+ # @param closable [Boolean] Whether or not the modal should allow closing.
37
+ #
38
+ # @param title [String] A simple title that you would like the component to
39
+ # render above the main content of the modal. Accessible through the
40
+ # {simple_title} accessor.
41
+ #
42
+ def initialize(*args, **kws, &block)
43
+ super
44
+
45
+ @dialog_id ||= SecureRandom.uuid
46
+ @closable = config_option(:closable, true)
47
+ @simple_title = config_option(:title)
48
+ end
49
+
50
+ def before_render
51
+ setup_component
52
+ setup_backdrop
53
+ setup_box
54
+ setup_close_icon
55
+ setup_title
56
+ setup_actions
57
+ end
58
+
59
+ private
60
+
61
+ def setup_component
62
+ set_tag_name(:component, :dialog)
63
+ add_html(:component, id: dialog_id)
64
+ add_css(:component, "modal")
65
+ end
66
+
67
+ def setup_backdrop
68
+ set_tag_name(:backdrop, :form)
69
+ add_html(:backdrop, { method: "dialog" })
70
+ add_css(:backdrop, "modal-backdrop")
71
+ end
72
+
73
+ def setup_box
74
+ add_css(:box, "modal-box relative")
75
+ end
76
+
77
+ def setup_close_icon
78
+ set_tag_name(:close_icon_wrapper, :form)
79
+ add_html(:close_icon_wrapper, { method: "dialog" })
80
+
81
+ set_tag_name(:close_icon, :button)
82
+ add_css(:close_icon, "absolute top-2 right-2 p-1 btn btn-circle btn-ghost btn-xs")
83
+ end
84
+
85
+ def setup_title
86
+ add_css(:title, "mb-2 text-xl font-bold")
87
+ end
88
+
89
+ def setup_actions
90
+ add_css(:actions, "mt-2 flex flex-row items-center justify-between")
91
+ end
92
+ end
@@ -0,0 +1,17 @@
1
+ = part(:component) do
2
+ = part(:checkbox)
3
+
4
+ - if on?
5
+ = on
6
+ - elsif @simple_on
7
+ = part(:on) do
8
+ = @simple_on
9
+
10
+ - if off?
11
+ = off
12
+ - elsif @simple_off
13
+ = part(:off) do
14
+ = @simple_off
15
+
16
+ - if indeterminate?
17
+ = indeterminate
@@ -0,0 +1,56 @@
1
+ class Daisy::Actions::SwapComponent < LocoMotion.configuration.base_component_class
2
+ class SwapOn < LocoMotion::BasicComponent
3
+ def before_render
4
+ add_css(:component, "swap-on")
5
+ end
6
+ end
7
+
8
+ class SwapOff < LocoMotion::BasicComponent
9
+ def before_render
10
+ add_css(:component, "swap-off")
11
+ end
12
+ end
13
+
14
+ class SwapIndeterminate < LocoMotion::BasicComponent
15
+ def before_render
16
+ add_css(:component, "swap-indeterminate")
17
+ end
18
+ end
19
+
20
+ define_parts :checkbox, :on, :off
21
+
22
+ renders_one :on, SwapOn
23
+ renders_one :off, SwapOff
24
+ renders_one :indeterminate, SwapIndeterminate
25
+
26
+ attr_reader :simple_on, :simple_off
27
+
28
+ def initialize(*args, **kwargs, &block)
29
+ super
30
+
31
+ @checked = config_option(:checked, false)
32
+ @simple_on = config_option(:on)
33
+ @simple_off = config_option(:off)
34
+ end
35
+
36
+ def before_render
37
+ setup_component
38
+ setup_checkbox
39
+ setup_on_off
40
+ end
41
+
42
+ def setup_component
43
+ set_tag_name(:component, :label)
44
+ add_css(:component, "swap")
45
+ end
46
+
47
+ def setup_checkbox
48
+ set_tag_name(:checkbox, :input)
49
+ add_html(:checkbox, { type: "checkbox", checked: @checked })
50
+ end
51
+
52
+ def setup_on_off
53
+ add_css(:on, "swap-on")
54
+ add_css(:off, "swap-off")
55
+ end
56
+ end
@@ -0,0 +1,5 @@
1
+ = part(:component) do
2
+ - SOME_THEMES.map do |theme|
3
+ %label.label.cursor-pointer.gap-4
4
+ %span.label-text= theme.titleize
5
+ %input.radio.theme-controller{ name: "theme", type: "radio", value: theme, checked: theme == "light"}
@@ -0,0 +1,8 @@
1
+ # Renders a very basic radio-button theme controller.
2
+ class Daisy::Actions::ThemeControllerComponent < LocoMotion.configuration.base_component_class
3
+ SOME_THEMES = ["light", "dark", "synthwave", "retro", "cyberpunk", "wireframe"].freeze
4
+
5
+ def before_render
6
+ add_css(:component, "flex flex-col lg:flex-row gap-4 items-center")
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ = part(:component) do
2
+ - sections.each do |section|
3
+ - section.set_loco_parent(component_ref)
4
+ = section
@@ -0,0 +1,82 @@
1
+ # The Accordion component shows sections that can be expanded or collapsed.
2
+ class Daisy::DataDisplay::AccordionComponent < LocoMotion.configuration.base_component_class
3
+
4
+ # Renders a single section of the accordion.
5
+ class AccordionSectionComponent < LocoMotion::BasicComponent
6
+ define_parts :radio_button, :title, :content
7
+
8
+ renders_one :title
9
+
10
+ # @return [String] Accessor for the `title` string passed via the component
11
+ # config.
12
+ attr_reader :simple_title
13
+
14
+ def initialize(*args, **kws, &block)
15
+ super
16
+
17
+ @value = config_option(:value)
18
+ @checked = config_option(:checked, false)
19
+ @simple_title = config_option(:title)
20
+ @name = config_option(:name)
21
+ end
22
+
23
+ def before_render
24
+ setup_component
25
+ setup_radio_button
26
+ setup_title
27
+ setup_content
28
+ end
29
+
30
+ def setup_component
31
+ # Reset the name to the config option or the parent name if available
32
+ @name = config_option(:name, loco_parent&.name)
33
+
34
+ add_css(:component, "collapse")
35
+ add_css(:component, "collapse-arrow") if loco_parent.config.modifiers.include?(:arrow)
36
+ add_css(:component, "collapse-plus") if loco_parent.config.modifiers.include?(:plus)
37
+ end
38
+
39
+ def setup_radio_button
40
+ set_tag_name(:radio_button, :input)
41
+ add_html(:radio_button, { type: "radio", name: @name, value: @value, checked: @checked })
42
+ end
43
+
44
+ def setup_title
45
+ set_tag_name(:title, :h2)
46
+ add_css(:title, "collapse-title text-lg font-bold")
47
+ end
48
+
49
+ def setup_content
50
+ add_css(:content, "collapse-content")
51
+ end
52
+
53
+ def call
54
+ part(:component) do
55
+ # Render the radio button which allows opening / closing
56
+ concat(part(:radio_button))
57
+
58
+ # Render the title slot, or simple title if provided
59
+ if title?
60
+ concat(title)
61
+ elsif @simple_title.present?
62
+ concat(part(:title) { @simple_title })
63
+ end
64
+
65
+ # Render the content
66
+ concat(part(:content) { content })
67
+ end
68
+ end
69
+ end
70
+
71
+ define_modifiers :arrow, :plus
72
+
73
+ renders_many :sections, AccordionSectionComponent
74
+
75
+ attr_reader :name
76
+
77
+ def initialize(*args, **kws, &block)
78
+ super
79
+
80
+ @name = config_option(:name, "accordion-#{SecureRandom.uuid}")
81
+ end
82
+ end
@@ -0,0 +1,9 @@
1
+ = part(:component) do
2
+ = part(:wrapper) do
3
+ - if @src.present?
4
+ = part(:img)
5
+ - elsif @icon.present?
6
+ = heroicon_tag(@icon, **rendered_html(:icon))
7
+ - else
8
+ = part(:placeholder) do
9
+ = content
@@ -0,0 +1,60 @@
1
+ # The Avatar Component displays in image, icon, or placeholder text to represent
2
+ # a user.
3
+ #
4
+ # It utilizes the CSS `where()` pseudo-class to reduce the specificity to 0 to
5
+ # allow for easy overriding while giving you some sane defaults.
6
+ #
7
+ # - Width: <code>w-24</code> (can override with w-10, h-10, etc.)
8
+ # - Corners: `rounded-full`
9
+ #
10
+ # If no image is provided, these additional classes will be added so that any
11
+ # text or icons are visible.
12
+ #
13
+ # - Background: +bg-neutral+
14
+ # - Text Color: `text-neutral-content`
15
+ #
16
+ # ## Examples
17
+ #
18
+ # ```language-haml
19
+ # - # Display an avatar with an image
20
+ # = daisy_avatar src: "https://example.com/avatar.jpg"
21
+ #
22
+ # - # Display an avatar with an icon
23
+ # = daisy_avatar icon: "user", icon_css: "text-yellow-400"
24
+ # ```
25
+ #
26
+ class Daisy::DataDisplay::AvatarComponent < LocoMotion.configuration.base_component_class
27
+ set_component_name :avatar
28
+
29
+ define_parts :wrapper, :img, :icon, :placeholder
30
+
31
+ # Create a new avatar component.
32
+ def initialize(*args, **kws, &block)
33
+ super
34
+
35
+ @src = config_option(:src)
36
+ @icon = config_option(:icon)
37
+ end
38
+
39
+ def before_render
40
+ setup_component
41
+ end
42
+
43
+ private
44
+
45
+ def setup_component
46
+ add_css(:component, "avatar")
47
+
48
+ # The where pseudo class reduces the specificity of the CSS selector to 0 so
49
+ # that other Tailwind classes provided by the user will take presedence.
50
+ add_css(:wrapper, "[:where(&)]:w-24 [:where(&)]:rounded-full")
51
+
52
+ if @src.present?
53
+ set_tag_name(:img, :img)
54
+ add_html(:img, { src: @src, title: @content })
55
+ else
56
+ add_css(:component, "placeholder")
57
+ add_css(:wrapper, "[:where(&)]:bg-neutral [:where(&)]:text-neutral-content")
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,2 @@
1
+ = part(:component) do
2
+ = content
@@ -0,0 +1,27 @@
1
+ #
2
+ # The Badge component renders as a small, rounded element with various
3
+ # background colors.
4
+ #
5
+ # @!parse class Daisy::DataDisplay::BadgeComponent < LocoMotion::BaseComponent; end
6
+ class Daisy::DataDisplay::BadgeComponent < LocoMotion.configuration.base_component_class
7
+ set_component_name :badge
8
+
9
+ #
10
+ # Create a new Badge component.
11
+ #
12
+ def initialize(*args, **kws, &block)
13
+ super
14
+
15
+ set_tag_name(:component, :span)
16
+ end
17
+
18
+ def before_render
19
+ setup_component
20
+ end
21
+
22
+ private
23
+
24
+ def setup_component
25
+ add_css(:component, "badge")
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ = part(:component) do
2
+ - if top_figure?
3
+ = top_figure
4
+
5
+ = part(:body) do
6
+ - if title?
7
+ = title
8
+ - elsif @simple_title
9
+ %h2.card-title= @simple_title
10
+
11
+ = content
12
+
13
+ - if actions?
14
+ = actions
15
+
16
+ - if bottom_figure?
17
+ = bottom_figure
@@ -0,0 +1,53 @@
1
+ class Daisy::DataDisplay::CardComponent < LocoMotion.configuration.base_component_class
2
+
3
+ Figure = LocoMotion::BasicComponent.build do
4
+ define_part :image, tag_name: :img, css: "card-image"
5
+
6
+ def initialize(*args, **kws, &block)
7
+ super
8
+
9
+ @src = kws[:src]
10
+ end
11
+
12
+ def before_render
13
+ set_tag_name(:component, :figure)
14
+ add_html(:image, src: @src) if @src
15
+ end
16
+
17
+ def call
18
+ part(:component) do
19
+ if @src
20
+ part(:image)
21
+ else
22
+ content
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ define_parts :body, :title
29
+
30
+ renders_one :title, LocoMotion::BasicComponent.build(tag_name: :h2, css: "card-title")
31
+ renders_one :top_figure, Figure
32
+ renders_one :bottom_figure, Figure
33
+ renders_one :actions, LocoMotion::BasicComponent.build(css: "card-actions")
34
+
35
+ def initialize(*args, **kws, &block)
36
+ super
37
+
38
+ @simple_title = kws[:title]
39
+ end
40
+
41
+ def before_render
42
+ setup_component
43
+ setup_body
44
+ end
45
+
46
+ def setup_component
47
+ add_css(:component, "card")
48
+ end
49
+
50
+ def setup_body
51
+ add_css(:body, "card-body")
52
+ end
53
+ end
@@ -0,0 +1,3 @@
1
+ = part(:component) do
2
+ - items.each do |item|
3
+ = item
@@ -0,0 +1,17 @@
1
+ class Daisy::DataDisplay::CarouselComponent < LocoMotion.configuration.base_component_class
2
+ class ItemComponent < LocoMotion::BasicComponent
3
+ def before_render
4
+ add_css(:component, "carousel-item")
5
+ end
6
+ end
7
+
8
+ renders_many :items, ItemComponent
9
+
10
+ def before_render
11
+ setup_component
12
+ end
13
+
14
+ def setup_component
15
+ add_css(:component, "carousel")
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ = part(:component) do
2
+ - if avatar?
3
+ = avatar
4
+
5
+ - if header?
6
+ = header
7
+
8
+ - bubbles.each do |bubble|
9
+ = bubble
10
+
11
+ = content
12
+
13
+ - if footer?
14
+ = footer
@@ -0,0 +1,38 @@
1
+ #
2
+ # The {ChatComponent} renders a bubble-like chat interface with an optional
3
+ # avatar, header, and footer.
4
+ #
5
+ # @slot avatar Renders an {AvatarComponent}. Common options include:
6
+ # @option avatar [String] src The URL of the image to display.
7
+ # @option avatar [String] icon A heroicon to be displayed instead of an image.
8
+ #
9
+ # @slot header [LocoMotion::BasicComponent] Renders a single header.
10
+ # @slot footer [LocoMotion::BasicComponent] Renders a single footer.
11
+ # @slot bubble [LocoMotion::BasicComponent] Renders one or more bubbles.
12
+ #
13
+ # ## Examples
14
+ #
15
+ # ```language-haml
16
+ # = daisy_chat(css: "border rounded-lg", html: { title: message.short_desc }) do |chat|
17
+ # - chat.with_bubble do
18
+ # I can't believe it's not the weekend yet!
19
+ # ```
20
+ #
21
+ class Daisy::DataDisplay::ChatComponent < LocoMotion.configuration.base_component_class
22
+ renders_one :avatar, Daisy::DataDisplay::AvatarComponent.build(css: "chat-image", icon_css: "size-6 text-base-100", wrapper_css: "w-10 rounded-full")
23
+ renders_one :header, LocoMotion::BasicComponent.build(css: "chat-header [:where(&)]:text-neutral-500")
24
+ renders_one :footer, LocoMotion::BasicComponent.build(css: "chat-footer [:where(&)]:text-neutral-500")
25
+
26
+ renders_many :bubbles, LocoMotion::BasicComponent.build(css: "chat-bubble")
27
+
28
+ #
29
+ # Sets up the component with various CSS classes and HTML attributes.
30
+ #
31
+ # - `chat` is always added
32
+ # - `chat-start` is added if the component does not already have `chat-start` or `chat-end`
33
+ #
34
+ def before_render
35
+ add_css(:component, "chat")
36
+ add_css(:component, "chat-start") unless rendered_css(:component).match?("chat-(start|end)")
37
+ end
38
+ end