daisyui 1.0.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 (79) hide show
  1. checksums.yaml +7 -0
  2. data/lib/daisy_ui/accordion.rb +49 -0
  3. data/lib/daisy_ui/alert.rb +76 -0
  4. data/lib/daisy_ui/avatar.rb +41 -0
  5. data/lib/daisy_ui/avatar_group.rb +19 -0
  6. data/lib/daisy_ui/badge.rb +118 -0
  7. data/lib/daisy_ui/base.rb +239 -0
  8. data/lib/daisy_ui/breadcrumbs.rb +25 -0
  9. data/lib/daisy_ui/button.rb +197 -0
  10. data/lib/daisy_ui/calendar.rb +48 -0
  11. data/lib/daisy_ui/card.rb +73 -0
  12. data/lib/daisy_ui/carousel.rb +51 -0
  13. data/lib/daisy_ui/chat.rb +49 -0
  14. data/lib/daisy_ui/checkbox.rb +112 -0
  15. data/lib/daisy_ui/collapse.rb +53 -0
  16. data/lib/daisy_ui/collapsible_sub_menu.rb +55 -0
  17. data/lib/daisy_ui/configurable.rb +45 -0
  18. data/lib/daisy_ui/countdown.rb +16 -0
  19. data/lib/daisy_ui/diff.rb +28 -0
  20. data/lib/daisy_ui/divider.rb +103 -0
  21. data/lib/daisy_ui/dock.rb +65 -0
  22. data/lib/daisy_ui/drawer.rb +61 -0
  23. data/lib/daisy_ui/dropdown.rb +101 -0
  24. data/lib/daisy_ui/fab.rb +34 -0
  25. data/lib/daisy_ui/fieldset.rb +20 -0
  26. data/lib/daisy_ui/file_input.rb +117 -0
  27. data/lib/daisy_ui/filter.rb +21 -0
  28. data/lib/daisy_ui/footer.rb +44 -0
  29. data/lib/daisy_ui/form_control.rb +15 -0
  30. data/lib/daisy_ui/hero.rb +24 -0
  31. data/lib/daisy_ui/hover_gallery.rb +16 -0
  32. data/lib/daisy_ui/indicator.rb +65 -0
  33. data/lib/daisy_ui/input.rb +117 -0
  34. data/lib/daisy_ui/join.rb +35 -0
  35. data/lib/daisy_ui/kbd.rb +54 -0
  36. data/lib/daisy_ui/label.rb +15 -0
  37. data/lib/daisy_ui/link.rb +137 -0
  38. data/lib/daisy_ui/list.rb +37 -0
  39. data/lib/daisy_ui/loading.rb +146 -0
  40. data/lib/daisy_ui/mask.rb +167 -0
  41. data/lib/daisy_ui/menu.rb +79 -0
  42. data/lib/daisy_ui/menu_item.rb +50 -0
  43. data/lib/daisy_ui/mockup_browser.rb +20 -0
  44. data/lib/daisy_ui/mockup_code.rb +16 -0
  45. data/lib/daisy_ui/mockup_phone.rb +24 -0
  46. data/lib/daisy_ui/mockup_window.rb +16 -0
  47. data/lib/daisy_ui/modal.rb +77 -0
  48. data/lib/daisy_ui/navbar.rb +31 -0
  49. data/lib/daisy_ui/pagination.rb +37 -0
  50. data/lib/daisy_ui/progress.rb +75 -0
  51. data/lib/daisy_ui/radial_progress.rb +181 -0
  52. data/lib/daisy_ui/radio.rb +110 -0
  53. data/lib/daisy_ui/range.rb +110 -0
  54. data/lib/daisy_ui/rating.rb +68 -0
  55. data/lib/daisy_ui/select.rb +117 -0
  56. data/lib/daisy_ui/skeleton.rb +19 -0
  57. data/lib/daisy_ui/stack.rb +47 -0
  58. data/lib/daisy_ui/stat.rb +57 -0
  59. data/lib/daisy_ui/status.rb +110 -0
  60. data/lib/daisy_ui/steps.rb +41 -0
  61. data/lib/daisy_ui/sub_menu.rb +37 -0
  62. data/lib/daisy_ui/swap.rb +52 -0
  63. data/lib/daisy_ui/tab.rb +40 -0
  64. data/lib/daisy_ui/tab_with_content.rb +72 -0
  65. data/lib/daisy_ui/tab_without_content.rb +40 -0
  66. data/lib/daisy_ui/table.rb +81 -0
  67. data/lib/daisy_ui/table_row.rb +33 -0
  68. data/lib/daisy_ui/tabs.rb +80 -0
  69. data/lib/daisy_ui/textarea.rb +117 -0
  70. data/lib/daisy_ui/theme_controller.rb +64 -0
  71. data/lib/daisy_ui/timeline.rb +66 -0
  72. data/lib/daisy_ui/toast.rb +61 -0
  73. data/lib/daisy_ui/toggle.rb +110 -0
  74. data/lib/daisy_ui/tooltip.rb +107 -0
  75. data/lib/daisy_ui/updated_at.rb +7 -0
  76. data/lib/daisy_ui/validator.rb +25 -0
  77. data/lib/daisy_ui/version.rb +5 -0
  78. data/lib/daisy_ui.rb +17 -0
  79. metadata +156 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3a564d7aec76c78ac4e110e35fd555266479b9227fbafd15ee71eb0a60de5d2e
4
+ data.tar.gz: 42613dc36df55a9c948909b261eeda51b3cd0856f3fb270a2c7fef7c17516713
5
+ SHA512:
6
+ metadata.gz: 2f68431a6c62e5c0c947b013e1a7b0383cb9f6b5b273f5a9bb97a91fe1f9ab41412fa5969f32b58bef6cdf1dc5146b372b0be9e6ec51bdbde84923457d27d57c
7
+ data.tar.gz: 6edad53184274486618aa899945046b4eac33d98d63a02b2a6d79b5b887485e6170091635e5f0597967e3a059e00fbdab23ec48607ddfe95c54cb56c4e17faac
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaisyUI
4
+ # @component html class="collapse"
5
+ class Accordion < Base
6
+ self.component_class = :collapse
7
+
8
+ def initialize(*, name:, checked: false, as: :div, **)
9
+ super(*, as:, **)
10
+ @name = name
11
+ @checked = checked
12
+ end
13
+
14
+ def view_template(&block)
15
+ public_send(as, class: classes, **attributes) do
16
+ input(type: :radio, name:, checked:)
17
+ div(class: "collapse-title", &title_block) if title_block
18
+ div(class: "collapse-content", &block) if block
19
+ end
20
+ end
21
+
22
+ def title(&block)
23
+ @title_block = block
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :name, :checked, :title_block
29
+
30
+ register_modifiers(
31
+ # "sm:collapse-arrow"
32
+ # "md:collapse-arrow"
33
+ # "lg:collapse-arrow"
34
+ arrow: "collapse-arrow",
35
+ # "sm:collapse-plus"
36
+ # "md:collapse-plus"
37
+ # "lg:collapse-plus"
38
+ plus: "collapse-plus",
39
+ # "sm:collapse-open"
40
+ # "md:collapse-open"
41
+ # "lg:collapse-open"
42
+ open: "collapse-open",
43
+ # "sm:collapse-close"
44
+ # "md:collapse-close"
45
+ # "lg:collapse-close"
46
+ close: "collapse-close"
47
+ )
48
+ end
49
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaisyUI
4
+ class Alert < Base
5
+ self.component_class = :alert
6
+
7
+ def initialize(*, as: :div, **)
8
+ super
9
+ end
10
+
11
+ def view_template(&)
12
+ public_send(as, role: :alert, class: classes, **attributes, &)
13
+ end
14
+
15
+ private
16
+
17
+ register_modifiers(
18
+ # "sm:alert-info"
19
+ # "@sm:alert-info"
20
+ # "md:alert-info"
21
+ # "@md:alert-info"
22
+ # "lg:alert-info"
23
+ # "@lg:alert-info"
24
+ info: "alert-info",
25
+ # "sm:alert-success"
26
+ # "@sm:alert-success"
27
+ # "md:alert-success"
28
+ # "@md:alert-success"
29
+ # "lg:alert-success"
30
+ # "@lg:alert-success"
31
+ success: "alert-success",
32
+ # "sm:alert-warning"
33
+ # "@sm:alert-warning"
34
+ # "md:alert-warning"
35
+ # "@md:alert-warning"
36
+ # "lg:alert-warning"
37
+ # "@lg:alert-warning"
38
+ warning: "alert-warning",
39
+ # "sm:alert-error"
40
+ # "@sm:alert-error"
41
+ # "md:alert-error"
42
+ # "@md:alert-error"
43
+ # "lg:alert-error"
44
+ # "@lg:alert-error"
45
+ error: "alert-error",
46
+ # "sm:alert-neutral"
47
+ # "@sm:alert-neutral"
48
+ # "md:alert-neutral"
49
+ # "@md:alert-neutral"
50
+ # "lg:alert-neutral"
51
+ # "@lg:alert-neutral"
52
+ neutral: "alert-neutral",
53
+ # "sm:alert-primary"
54
+ # "@sm:alert-primary"
55
+ # "md:alert-primary"
56
+ # "@md:alert-primary"
57
+ # "lg:alert-primary"
58
+ # "@lg:alert-primary"
59
+ primary: "alert-primary",
60
+ # "sm:alert-secondary"
61
+ # "@sm:alert-secondary"
62
+ # "md:alert-secondary"
63
+ # "@md:alert-secondary"
64
+ # "lg:alert-secondary"
65
+ # "@lg:alert-secondary"
66
+ secondary: "alert-secondary",
67
+ # "sm:alert-accent"
68
+ # "@sm:alert-accent"
69
+ # "md:alert-accent"
70
+ # "@md:alert-accent"
71
+ # "lg:alert-accent"
72
+ # "@lg:alert-accent"
73
+ accent: "alert-accent"
74
+ )
75
+ end
76
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaisyUI
4
+ class Avatar < Base
5
+ self.component_class = :avatar
6
+
7
+ def initialize(*, as: :div, **)
8
+ super
9
+ end
10
+
11
+ def view_template(&)
12
+ public_send(as, class: classes, **attributes, &)
13
+ end
14
+
15
+ private
16
+
17
+ register_modifiers(
18
+ # "sm:online"
19
+ # "@sm:online"
20
+ # "md:online"
21
+ # "@md:online"
22
+ # "lg:online"
23
+ # "@lg:online"
24
+ online: "online",
25
+ # "sm:offline"
26
+ # "@sm:offline"
27
+ # "md:offline"
28
+ # "@md:offline"
29
+ # "lg:offline"
30
+ # "@lg:offline"
31
+ offline: "offline",
32
+ # "sm:placeholder"
33
+ # "@sm:placeholder"
34
+ # "md:placeholder"
35
+ # "@md:placeholder"
36
+ # "lg:placeholder"
37
+ # "@lg:placeholder"
38
+ placeholder: "placeholder"
39
+ )
40
+ end
41
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaisyUI
4
+ class AvatarGroup < Base
5
+ self.component_class = "avatar-group"
6
+
7
+ def initialize(*, as: :div, **)
8
+ super
9
+ end
10
+
11
+ def view_template(&)
12
+ public_send(as, class: classes, **attributes, &)
13
+ end
14
+
15
+ def avatar(*, **, &)
16
+ render DaisyUI::Avatar.new(*, **, &)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaisyUI
4
+ class Badge < Base
5
+ self.component_class = :badge
6
+
7
+ def initialize(*, as: :span, **)
8
+ super
9
+ end
10
+
11
+ def view_template(&)
12
+ public_send(as, class: classes, **attributes, &)
13
+ end
14
+
15
+ private
16
+
17
+ register_modifiers(
18
+ # "sm:badge-neutral"
19
+ # "@sm:badge-neutral"
20
+ # "md:badge-neutral"
21
+ # "@md:badge-neutral"
22
+ # "lg:badge-neutral"
23
+ # "@lg:badge-neutral"
24
+ neutral: "badge-neutral",
25
+ # "sm:badge-primary"
26
+ # "@sm:badge-primary"
27
+ # "md:badge-primary"
28
+ # "@md:badge-primary"
29
+ # "lg:badge-primary"
30
+ # "@lg:badge-primary"
31
+ primary: "badge-primary",
32
+ # "sm:badge-secondary"
33
+ # "@sm:badge-secondary"
34
+ # "md:badge-secondary"
35
+ # "@md:badge-secondary"
36
+ # "lg:badge-secondary"
37
+ # "@lg:badge-secondary"
38
+ secondary: "badge-secondary",
39
+ # "sm:badge-accent"
40
+ # "@sm:badge-accent"
41
+ # "md:badge-accent"
42
+ # "@md:badge-accent"
43
+ # "lg:badge-accent"
44
+ # "@lg:badge-accent"
45
+ accent: "badge-accent",
46
+ # "sm:badge-ghost"
47
+ # "@sm:badge-ghost"
48
+ # "md:badge-ghost"
49
+ # "@md:badge-ghost"
50
+ # "lg:badge-ghost"
51
+ # "@lg:badge-ghost"
52
+ ghost: "badge-ghost",
53
+ # "sm:badge-info"
54
+ # "@sm:badge-info"
55
+ # "md:badge-info"
56
+ # "@md:badge-info"
57
+ # "lg:badge-info"
58
+ # "@lg:badge-info"
59
+ info: "badge-info",
60
+ # "sm:badge-success"
61
+ # "@sm:badge-success"
62
+ # "md:badge-success"
63
+ # "@md:badge-success"
64
+ # "lg:badge-success"
65
+ # "@lg:badge-success"
66
+ success: "badge-success",
67
+ # "sm:badge-warning"
68
+ # "@sm:badge-warning"
69
+ # "md:badge-warning"
70
+ # "@md:badge-warning"
71
+ # "lg:badge-warning"
72
+ # "@lg:badge-warning"
73
+ warning: "badge-warning",
74
+ # "sm:badge-error"
75
+ # "@sm:badge-error"
76
+ # "md:badge-error"
77
+ # "@md:badge-error"
78
+ # "lg:badge-error"
79
+ # "@lg:badge-error"
80
+ error: "badge-error",
81
+ # "sm:badge-outline"
82
+ # "@sm:badge-outline"
83
+ # "md:badge-outline"
84
+ # "@md:badge-outline"
85
+ # "lg:badge-outline"
86
+ # "@lg:badge-outline"
87
+ outline: "badge-outline",
88
+ # "sm:badge-lg"
89
+ # "@sm:badge-lg"
90
+ # "md:badge-lg"
91
+ # "@md:badge-lg"
92
+ # "lg:badge-lg"
93
+ # "@lg:badge-lg"
94
+ lg: "badge-lg",
95
+ # "sm:badge-md"
96
+ # "@sm:badge-md"
97
+ # "md:badge-md"
98
+ # "@md:badge-md"
99
+ # "lg:badge-md"
100
+ # "@lg:badge-md"
101
+ md: "badge-md",
102
+ # "sm:badge-sm"
103
+ # "@sm:badge-sm"
104
+ # "md:badge-sm"
105
+ # "@md:badge-sm"
106
+ # "lg:badge-sm"
107
+ # "@lg:badge-sm"
108
+ sm: "badge-sm",
109
+ # "sm:badge-xs"
110
+ # "@sm:badge-xs"
111
+ # "md:badge-xs"
112
+ # "@md:badge-xs"
113
+ # "lg:badge-xs"
114
+ # "@lg:badge-xs"
115
+ xs: "badge-xs"
116
+ )
117
+ end
118
+ end
@@ -0,0 +1,239 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaisyUI
4
+ class Base < Phlex::HTML
5
+ # Shared color modifiers used across multiple components
6
+ # Maps color names to their DaisyUI background/text class combinations
7
+ COLOR_MODIFIERS = {
8
+ # "sm:bg-primary sm:text-primary-content"
9
+ # "@sm:bg-primary @sm:text-primary-content"
10
+ # "md:bg-primary md:text-primary-content"
11
+ # "@md:bg-primary @md:text-primary-content"
12
+ # "lg:bg-primary lg:text-primary-content"
13
+ # "@lg:bg-primary @lg:text-primary-content"
14
+ primary: "bg-primary text-primary-content",
15
+ # "sm:bg-secondary sm:text-secondary-content"
16
+ # "@sm:bg-secondary @sm:text-secondary-content"
17
+ # "md:bg-secondary md:text-secondary-content"
18
+ # "@md:bg-secondary @md:text-secondary-content"
19
+ # "lg:bg-secondary lg:text-secondary-content"
20
+ # "@lg:bg-secondary @lg:text-secondary-content"
21
+ secondary: "bg-secondary text-secondary-content",
22
+ # "sm:bg-accent sm:text-accent-content"
23
+ # "@sm:bg-accent @sm:text-accent-content"
24
+ # "md:bg-accent md:text-accent-content"
25
+ # "@md:bg-accent @md:text-accent-content"
26
+ # "lg:bg-accent lg:text-accent-content"
27
+ # "@lg:bg-accent @lg:text-accent-content"
28
+ accent: "bg-accent text-accent-content",
29
+ # "sm:bg-neutral sm:text-neutral-content"
30
+ # "@sm:bg-neutral @sm:text-neutral-content"
31
+ # "md:bg-neutral md:text-neutral-content"
32
+ # "@md:bg-neutral @md:text-neutral-content"
33
+ # "lg:bg-neutral lg:text-neutral-content"
34
+ # "@lg:bg-neutral @lg:text-neutral-content"
35
+ neutral: "bg-neutral text-neutral-content",
36
+ # "sm:bg-base-100 sm:text-base-content"
37
+ # "@sm:bg-base-100 @sm:text-base-content"
38
+ # "md:bg-base-100 md:text-base-content"
39
+ # "@md:bg-base-100 @md:text-base-content"
40
+ # "lg:bg-base-100 lg:text-base-content"
41
+ # "@lg:bg-base-100 @lg:text-base-content"
42
+ base_100: "bg-base-100 text-base-content",
43
+ # "sm:bg-base-200 sm:text-base-content"
44
+ # "@sm:bg-base-200 @sm:text-base-content"
45
+ # "md:bg-base-200 md:text-base-content"
46
+ # "@md:bg-base-200 @md:text-base-content"
47
+ # "lg:bg-base-200 lg:text-base-content"
48
+ # "@lg:bg-base-200 @lg:text-base-content"
49
+ base_200: "bg-base-200 text-base-content",
50
+ # "sm:bg-base-300 sm:text-base-content"
51
+ # "@sm:bg-base-300 @sm:text-base-content"
52
+ # "md:bg-base-300 md:text-base-content"
53
+ # "@md:bg-base-300 @md:text-base-content"
54
+ # "lg:bg-base-300 lg:text-base-content"
55
+ # "@lg:bg-base-300 @lg:text-base-content"
56
+ base_300: "bg-base-300 text-base-content",
57
+ # "sm:bg-info sm:text-info-content"
58
+ # "@sm:bg-info @sm:text-info-content"
59
+ # "md:bg-info md:text-info-content"
60
+ # "@md:bg-info @md:text-info-content"
61
+ # "lg:bg-info lg:text-info-content"
62
+ # "@lg:bg-info @lg:text-info-content"
63
+ info: "bg-info text-info-content",
64
+ # "sm:bg-success sm:text-success-content"
65
+ # "@sm:bg-success @sm:text-success-content"
66
+ # "md:bg-success md:text-success-content"
67
+ # "@md:bg-success @md:text-success-content"
68
+ # "lg:bg-success lg:text-success-content"
69
+ # "@lg:bg-success @lg:text-success-content"
70
+ success: "bg-success text-success-content",
71
+ # "sm:bg-warning sm:text-warning-content"
72
+ # "@sm:bg-warning @sm:text-warning-content"
73
+ # "md:bg-warning md:text-warning-content"
74
+ # "@md:bg-warning @md:text-warning-content"
75
+ # "lg:bg-warning lg:text-warning-content"
76
+ # "@lg:bg-warning @lg:text-warning-content"
77
+ warning: "bg-warning text-warning-content",
78
+ # "sm:bg-error sm:text-error-content"
79
+ # "@sm:bg-error @sm:text-error-content"
80
+ # "md:bg-error md:text-error-content"
81
+ # "@md:bg-error @md:text-error-content"
82
+ # "lg:bg-error lg:text-error-content"
83
+ # "@lg:bg-error @lg:text-error-content"
84
+ error: "bg-error text-error-content"
85
+ }.freeze
86
+
87
+ class << self
88
+ attr_writer :component_class
89
+ attr_accessor :modifiers
90
+
91
+ def component_class
92
+ return @component_class if instance_variable_defined?(:@component_class)
93
+
94
+ @component_class = begin
95
+ # Convert "DaisyUI::Button" -> "button"
96
+ class_name = name.split("::").last # demodulize
97
+ class_name.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
98
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
99
+ .tr("_", "-")
100
+ .downcase
101
+ end
102
+ end
103
+
104
+ def inherited(subclass)
105
+ super
106
+ subclass.modifiers = (modifiers || {}).dup
107
+ # Inherit component_class if it was explicitly set
108
+ if instance_variable_defined?(:@component_class)
109
+ subclass.component_class = @component_class
110
+ end
111
+ end
112
+
113
+ def register_modifiers(mods)
114
+ self.modifiers = (modifiers || {}).merge(mods)
115
+ end
116
+ end
117
+
118
+ def initialize(*modifiers, as: :div, id: nil, **options)
119
+ # Extract boolean modifiers from options (e.g., primary: true, secondary: false)
120
+ boolean_modifiers = extract_boolean_modifiers(options)
121
+
122
+ @modifiers = modifiers + boolean_modifiers
123
+ @as = as
124
+ @id = id
125
+ @options = options
126
+ end
127
+
128
+ private
129
+
130
+ attr_reader :modifiers, :options, :as, :id
131
+
132
+ # Main extension points - override these in your project!
133
+ def classes
134
+ merge_classes(
135
+ base_class,
136
+ *modifier_classes,
137
+ *responsive_classes,
138
+ options.delete(:class)
139
+ )
140
+ end
141
+
142
+ def attributes
143
+ merge_attributes(**options)
144
+ end
145
+
146
+ # Simple defaults - easy to override
147
+ def merge_classes(*parts)
148
+ result = parts.compact.join(" ")
149
+ result.empty? ? nil : result
150
+ end
151
+
152
+ def merge_attributes(**attrs)
153
+ attrs
154
+ end
155
+
156
+ # Core functionality
157
+ def base_class
158
+ # If responsive option includes `true`, base class should only appear with responsive prefix
159
+ if options[:responsive]&.values&.any? { |mods| Array(mods).include?(true) }
160
+ return nil
161
+ end
162
+
163
+ apply_prefix(self.class.component_class&.to_s)
164
+ end
165
+
166
+ def modifier_classes
167
+ modifiers.filter_map { |m| apply_prefix(modifier_map[m]) }
168
+ end
169
+
170
+ def responsive_classes
171
+ return [] unless (resp = options.delete(:responsive))
172
+
173
+ resp.flat_map do |breakpoint, mods|
174
+ Array(mods).flat_map do |mod|
175
+ # Handle `true` as a special value to apply responsive to base class
176
+ if mod == true
177
+ base_class_value = self.class.component_class
178
+ next unless base_class_value
179
+
180
+ "#{breakpoint}:#{apply_prefix(base_class_value)}"
181
+ else
182
+ # Get the modifier classes (may be multiple like "bg-primary text-primary-content")
183
+ modifier_classes = modifier_map[mod]
184
+ next unless modifier_classes
185
+
186
+ # Split and apply breakpoint prefix to each class
187
+ modifier_classes.split.map do |css_class|
188
+ "#{breakpoint}:#{apply_prefix(css_class)}"
189
+ end
190
+ end
191
+ end
192
+ end.compact
193
+ end
194
+
195
+ def modifier_map
196
+ {
197
+ skeleton: "skeleton",
198
+ **(self.class.modifiers || {}),
199
+ **DaisyUI.configuration.modifiers.for(component: self.class),
200
+ **DaisyUI.configuration.modifiers.for(component: nil)
201
+ }
202
+ end
203
+
204
+ def extract_boolean_modifiers(options)
205
+ modifier_keys = modifier_map.keys
206
+ boolean_mods = []
207
+
208
+ modifier_keys.each do |key|
209
+ if options.key?(key) && (options[key] == true || options[key] == false)
210
+ boolean_mods << key if options.delete(key) == true
211
+ end
212
+ end
213
+
214
+ boolean_mods
215
+ end
216
+
217
+ def apply_prefix(css_class)
218
+ return css_class unless css_class
219
+ return css_class unless (prefix = DaisyUI.configuration.prefix)
220
+
221
+ css_class.split.map { |c| "#{prefix}#{c}" }.join(" ")
222
+ end
223
+
224
+ # Helper for sub-components
225
+ # Builds CSS classes for sub-components, merging with any custom classes
226
+ def component_classes(*base_classes, options: self.options)
227
+ prefixed_classes = base_classes.map { |c| apply_prefix(c) }
228
+ merge_classes(*prefixed_classes, options.delete(:class))
229
+ end
230
+
231
+ def render_as(*, as:, **, &)
232
+ if as.is_a?(Symbol)
233
+ public_send(as, *, **, &)
234
+ else
235
+ render as.new(*, **, &)
236
+ end
237
+ end
238
+ end
239
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaisyUI
4
+ class Breadcrumbs < Base
5
+ self.component_class = :breadcrumbs
6
+
7
+ def initialize(*, as: :div, **)
8
+ super
9
+ end
10
+
11
+ def view_template(&)
12
+ public_send(as, class: classes, **attributes) do
13
+ ul(&)
14
+ end
15
+ end
16
+
17
+ def crumb(**opts, &)
18
+ li(class: component_classes(options: opts), **opts, &)
19
+ end
20
+ alias_method :breadcrumb, :crumb
21
+ alias_method :item, :crumb
22
+
23
+ register_modifiers({})
24
+ end
25
+ end