daisy_components 0.1.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 (56) hide show
  1. checksums.yaml +7 -0
  2. data/.cursor/rules/how-to-write-tests.mdc +67 -0
  3. data/.cursor/rules/preview-file-stucture.mdc +95 -0
  4. data/.cursorrules +64 -0
  5. data/.github/dependabot.yml +12 -0
  6. data/.github/workflows/ci.yml +65 -0
  7. data/.gitignore +13 -0
  8. data/.vscode/launch.json +55 -0
  9. data/.vscode/settings.json +44 -0
  10. data/CHANGELOG.md +39 -0
  11. data/Gemfile +32 -0
  12. data/Gemfile.lock +335 -0
  13. data/MIT-LICENSE +20 -0
  14. data/README.md +64 -0
  15. data/Rakefile +7 -0
  16. data/app/assets/images/daisy_components/.keep +0 -0
  17. data/app/assets/stylesheets/daisy_ui/application.css +15 -0
  18. data/app/components/daisy_ui/actions/button.rb +262 -0
  19. data/app/components/daisy_ui/actions/dropdown.rb +125 -0
  20. data/app/components/daisy_ui/actions/swap.rb +126 -0
  21. data/app/components/daisy_ui/base_component.rb +29 -0
  22. data/app/components/daisy_ui/data_display/accordion.rb +128 -0
  23. data/app/components/daisy_ui/data_display/accordion_item.rb +121 -0
  24. data/app/components/daisy_ui/data_display/avatar.rb +131 -0
  25. data/app/components/daisy_ui/data_display/avatar_group.rb +102 -0
  26. data/app/components/daisy_ui/data_display/badge.rb +126 -0
  27. data/app/components/daisy_ui/data_display/card/actions.rb +94 -0
  28. data/app/components/daisy_ui/data_display/card/body.rb +113 -0
  29. data/app/components/daisy_ui/data_display/card/figure.rb +44 -0
  30. data/app/components/daisy_ui/data_display/card/title.rb +56 -0
  31. data/app/components/daisy_ui/data_display/card.rb +157 -0
  32. data/app/components/daisy_ui/data_display/chat.rb +92 -0
  33. data/app/components/daisy_ui/data_display/chat_bubble/metadata.rb +71 -0
  34. data/app/components/daisy_ui/data_display/chat_bubble.rb +166 -0
  35. data/app/components/daisy_ui/divider.rb +9 -0
  36. data/app/components/daisy_ui/item.rb +20 -0
  37. data/app/components/daisy_ui/title.rb +9 -0
  38. data/app/controllers/concerns/.keep +0 -0
  39. data/app/controllers/daisy_ui/application_controller.rb +6 -0
  40. data/app/helpers/daisy_ui/application_helper.rb +6 -0
  41. data/app/helpers/daisy_ui/icons_helper.rb +296 -0
  42. data/app/views/layouts/daisyui/application.html.erb +17 -0
  43. data/bin/parse_coverage.rb +59 -0
  44. data/bin/rails +57 -0
  45. data/bin/rubocop +10 -0
  46. data/bin/scrape_component +86 -0
  47. data/daisy_components.gemspec +33 -0
  48. data/docs/assets/2025-01_screeshot_1.png +0 -0
  49. data/docs/assets/2025-01_screeshot_2.png +0 -0
  50. data/docs/assets/2025-01_screeshot_3.png +0 -0
  51. data/lib/daisy_components.rb +5 -0
  52. data/lib/daisy_ui/engine.rb +51 -0
  53. data/lib/daisy_ui/version.rb +5 -0
  54. data/lib/daisy_ui.rb +13 -0
  55. data/lib/tasks/daisy_ui_tasks.rake +6 -0
  56. metadata +112 -0
@@ -0,0 +1,296 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Layout/LineLength,Metrics/ModuleLength,Metrics/MethodLength,Metrics/AbcSize,Metrics/BlockLength
4
+ module DaisyUI
5
+ module IconsHelper
6
+ def hamburger_icon(size_class)
7
+ tag.svg(xmlns: 'http://www.w3.org/2000/svg', class: size_class, fill: 'none',
8
+ viewBox: '0 0 24 24', stroke: 'currentColor') do
9
+ tag.path(stroke_linecap: 'round', stroke_linejoin: 'round', stroke_width: '2',
10
+ d: 'M4 6h16M4 12h16M4 18h16')
11
+ end
12
+ end
13
+
14
+ def error_icon(size_class)
15
+ tag.svg(xmlns: 'http://www.w3.org/2000/svg', class: size_class, fill: 'currentColor', viewBox: '0 0 24 24') do
16
+ tag.g(fill: 'currentColor') do
17
+ tag.rect(x: '1.972', y: '11', width: '20.056', height: '2', transform: 'translate(-4.971 12) rotate(-45)', fill: 'currentColor', stroke_width: 0)
18
+ tag.path(d: 'm12,23c-6.065,0-11-4.935-11-11S5.935,1,12,1s11,4.935,11,11-4.935,11-11,11Zm0-20C7.038,3,3,7.037,3,12s4.038,9,9,9,9-4.037,9-9S16.962,3,12,3Z', stroke_width: 0, fill: 'currentColor')
19
+ end
20
+ end
21
+ end
22
+
23
+ def close_icon(size_class)
24
+ tag.svg(xmlns: 'http://www.w3.org/2000/svg', class: size_class, fill: 'currentColor',
25
+ viewBox: '0 0 24 24', stroke: 'currentColor') do
26
+ tag.path(stroke_linecap: 'round', stroke_linejoin: 'round', stroke_width: '2',
27
+ d: 'M6 18L18 6M6 6l12 12')
28
+ end
29
+ end
30
+
31
+ def volume_on_icon(size_class = '')
32
+ tag.svg(xmlns: 'http://www.w3.org/2000/svg', class: size_class, fill: 'currentColor',
33
+ viewBox: '0 0 24 24') do
34
+ tag.path(d: 'M14,3.23V5.29C16.89,6.15 19,8.83 19,12C19,15.17 16.89,17.84 14,18.7V20.77C18,19.86 21,16.28 21,12C21,7.72 18,4.14 14,3.23M16.5,12C16.5,10.23 15.5,8.71 14,7.97V16C15.5,15.29 16.5,13.76 16.5,12M3,9V15H7L12,20V4L7,9H3Z')
35
+ end
36
+ end
37
+
38
+ def volume_off_icon(size_class = '')
39
+ tag.svg(xmlns: 'http://www.w3.org/2000/svg', class: size_class, fill: 'currentColor',
40
+ viewBox: '0 0 24 24') do
41
+ tag.path(d: 'M3,9H7L12,4V20L7,15H3V9M16.59,12L14,9.41L15.41,8L18,10.59L20.59,8L22,9.41L19.41,12L22,14.59L20.59,16L18,13.41L15.41,16L14,14.59L16.59,12Z')
42
+ end
43
+ end
44
+
45
+ def sun_icon(size_class)
46
+ tag.svg(xmlns: 'http://www.w3.org/2000/svg', class: size_class, fill: 'none',
47
+ viewBox: '0 0 24 24', stroke: 'currentColor') do
48
+ path = 'M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-' \
49
+ '.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z'
50
+ tag.path(stroke_linecap: 'round', stroke_linejoin: 'round', stroke_width: '2', d: path)
51
+ end
52
+ end
53
+
54
+ def info_icon(size_class)
55
+ tag.svg(xmlns: 'http://www.w3.org/2000/svg', class: size_class, fill: 'none',
56
+ viewBox: '0 0 24 24') do
57
+ tag.path('stroke-linecap': 'round', 'stroke-linejoin': 'round', 'stroke-width': '2',
58
+ d: 'M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z')
59
+ end
60
+ end
61
+
62
+ def moon_icon(size_class)
63
+ tag.svg(xmlns: 'http://www.w3.org/2000/svg', class: size_class, fill: 'none',
64
+ viewBox: '0 0 24 24', stroke: 'currentColor') do
65
+ path = 'M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z'
66
+ tag.path(stroke_linecap: 'round', stroke_linejoin: 'round', stroke_width: '2', d: path)
67
+ end
68
+ end
69
+
70
+ def warning_icon(size_class)
71
+ tag.svg(xmlns: 'http://www.w3.org/2000/svg', class: size_class, fill: 'none',
72
+ viewBox: '0 0 24 24', stroke: 'currentColor') do
73
+ path = 'M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-' \
74
+ '1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z'
75
+ tag.path(stroke_linecap: 'round', stroke_linejoin: 'round', stroke_width: '2', d: path)
76
+ end
77
+ end
78
+
79
+ def chevron_down_icon(size_class)
80
+ tag.svg(xmlns: 'http://www.w3.org/2000/svg', class: size_class, fill: 'none',
81
+ viewBox: '0 0 24 24', stroke: 'currentColor') do
82
+ tag.path(stroke_linecap: 'round', stroke_linejoin: 'round', stroke_width: '2',
83
+ d: 'M19 9l-7 7-7-7')
84
+ end
85
+ end
86
+
87
+ def check_icon(size_class, stroke: 'none', fill: 'none')
88
+ tag.svg(xmlns: 'http://www.w3.org/2000/svg', class: size_class, fill: fill,
89
+ viewBox: '0 0 24 24', stroke: stroke) do
90
+ tag.path(stroke_linecap: 'round', strokelinejoin: 'round', stroke_width: '2',
91
+ d: 'M5 13l4 4L19 7')
92
+ end
93
+ end
94
+
95
+ def heart_icon(size_class)
96
+ tag.svg(xmlns: 'http://www.w3.org/2000/svg', fill: 'none', viewBox: '0 0 24 24',
97
+ 'stroke-width': '2.5', stroke: 'currentColor', class: size_class) do
98
+ tag.path('stroke-linecap': 'round', 'stroke-linejoin': 'round',
99
+ d: 'M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z')
100
+ end
101
+ end
102
+
103
+ def home_icon(size_class)
104
+ tag.svg(xmlns: 'http://www.w3.org/2000/svg', class: size_class, fill: 'none',
105
+ viewBox: '0 0 24 24', stroke: 'currentColor', stroke_width: '2.5') do
106
+ tag.path(stroke_linecap: 'round', stroke_linejoin: 'round',
107
+ d: 'M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25')
108
+ end
109
+ end
110
+
111
+ def email_icon(size_class)
112
+ tag.svg(aria_label: 'Email icon', class: size_class, xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 24 24') do
113
+ tag.g(stroke_linejoin: 'round', stroke_linecap: 'round', stroke_width: '2', fill: 'none', stroke: 'black') do
114
+ safe_join([
115
+ tag.rect(width: '20', height: '16', x: '2', y: '4', rx: '2'),
116
+ tag.path(d: 'm22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7')
117
+ ])
118
+ end
119
+ end
120
+ end
121
+
122
+ def github_icon(size_class)
123
+ tag.svg(aria_label: 'GitHub logo', class: size_class, xmlns: 'http://www.w3.org/2000/svg',
124
+ viewBox: '0 0 24 24') do
125
+ tag.path(fill: 'white',
126
+ d: 'M12,2A10,10 0 0,0 2,12C2,16.42 4.87,20.17 8.84,21.5C9.34,21.58 9.5,21.27 9.5,21C9.5,20.77 9.5,20.14 9.5,19.31C6.73,19.91 6.14,17.97 6.14,17.97C5.68,16.81 5.03,16.5 5.03,16.5C4.12,15.88 5.1,15.9 5.1,15.9C6.1,15.97 6.63,16.93 6.63,16.93C7.5,18.45 8.97,18 9.54,17.76C9.63,17.11 9.89,16.67 10.17,16.42C7.95,16.17 5.62,15.31 5.62,11.5C5.62,10.39 6,9.5 6.65,8.79C6.55,8.54 6.2,7.5 6.75,6.15C6.75,6.15 7.59,5.88 9.5,7.17C10.29,6.95 11.15,6.84 12,6.84C12.85,6.84 13.71,6.95 14.5,7.17C16.41,5.88 17.25,6.15 17.25,6.15C17.8,7.5 17.45,8.54 17.35,8.79C18,9.5 18.38,10.39 18.38,11.5C18.38,15.32 16.04,16.16 13.81,16.41C14.17,16.72 14.5,17.33 14.5,18.26C14.5,19.6 14.5,20.68 14.5,21C14.5,21.27 14.66,21.59 15.17,21.5C19.14,20.16 22,16.42 22,12A10,10 0 0,0 12,2Z')
127
+ end
128
+ end
129
+
130
+ def google_icon(size_class)
131
+ tag.svg(aria_label: 'Google logo', class: size_class, xmlns: 'http://www.w3.org/2000/svg',
132
+ viewBox: '0 0 512 512') do
133
+ tag.g do
134
+ safe_join([
135
+ tag.path(d: 'm0 0H512V512H0', fill: '#fff'),
136
+ tag.path(fill: '#34a853', d: 'M153 292c30 82 118 95 171 60h62v48A192 192 0 0190 341'),
137
+ tag.path(fill: '#4285f4', d: 'm386 400a140 175 0 0053-179H260v74h102q-7 37-38 57'),
138
+ tag.path(fill: '#fbbc02', d: 'm90 341a208 200 0 010-171l63 49q-12 37 0 73'),
139
+ tag.path(fill: '#ea4335', d: 'm153 219c22-69 116-109 179-50l55-54c-78-75-230-72-297 55')
140
+ ])
141
+ end
142
+ end
143
+ end
144
+
145
+ def facebook_icon(size_class)
146
+ tag.svg(aria_label: 'Facebook logo', class: size_class, xmlns: 'http://www.w3.org/2000/svg',
147
+ viewBox: '0 0 32 32') do
148
+ tag.path(fill: 'white', d: 'M8 12h5V8c0-6 4-7 11-6v5c-4 0-5 0-5 3v2h5l-1 6h-4v12h-6V18H8z')
149
+ end
150
+ end
151
+
152
+ def x_icon(size_class)
153
+ tag.svg(aria_label: 'X logo', class: size_class, viewBox: '0 0 300 271', xmlns: 'http://www.w3.org/2000/svg') do
154
+ tag.path(fill: 'currentColor',
155
+ d: 'm236 0h46l-101 115 118 156h-92.6l-72.5-94.8-83 94.8h-46l107-123-113-148h94.9l65.5 86.6zm-16.1 244h25.5l-165-218h-27.4z')
156
+ end
157
+ end
158
+
159
+ def kakao_icon(size_class)
160
+ tag.svg(aria_label: 'Kakao logo', class: size_class, viewBox: '0 0 512 512',
161
+ xmlns: 'http://www.w3.org/2000/svg') do
162
+ tag.path(fill: '#181600',
163
+ d: 'M255.5 48C299.345 48 339.897 56.5332 377.156 73.5996C414.415 90.666 443.871 113.873 465.522 143.22C487.174 172.566 498 204.577 498 239.252C498 273.926 487.174 305.982 465.522 335.42C443.871 364.857 414.46 388.109 377.291 405.175C340.122 422.241 299.525 430.775 255.5 430.775C241.607 430.775 227.262 429.781 212.467 427.795C148.233 472.402 114.042 494.977 109.892 495.518C107.907 496.241 106.012 496.15 104.208 495.248C103.486 494.706 102.945 493.983 102.584 493.08C102.223 492.177 102.043 491.365 102.043 490.642V489.559C103.126 482.515 111.335 453.169 126.672 401.518C91.8486 384.181 64.1974 361.2 43.7185 332.575C23.2395 303.951 13 272.843 13 239.252C13 204.577 23.8259 172.566 45.4777 143.22C67.1295 113.873 96.5849 90.666 133.844 73.5996C171.103 56.5332 211.655 48 255.5 48Z')
164
+ end
165
+ end
166
+
167
+ def apple_icon(size_class)
168
+ tag.svg(aria_label: 'Apple logo', class: size_class, xmlns: 'http://www.w3.org/2000/svg',
169
+ viewBox: '0 0 1195 1195') do
170
+ tag.path(fill: 'white',
171
+ d: 'M1006.933 812.8c-32 153.6-115.2 211.2-147.2 249.6-32 25.6-121.6 25.6-153.6 6.4-38.4-25.6-134.4-25.6-166.4 0-44.8 32-115.2 19.2-128 12.8-256-179.2-352-716.8 12.8-774.4 64-12.8 134.4 32 134.4 32 51.2 25.6 70.4 12.8 115.2-6.4 96-44.8 243.2-44.8 313.6 76.8-147.2 96-153.6 294.4 19.2 403.2zM802.133 64c12.8 70.4-64 224-204.8 230.4-12.8-38.4 32-217.6 204.8-230.4z')
172
+ end
173
+ end
174
+
175
+ def amazon_icon(size_class)
176
+ tag.svg(aria_label: 'Amazon logo', class: size_class, xmlns: 'http://www.w3.org/2000/svg',
177
+ viewBox: '0 0 16 16') do
178
+ tag.g(fill: 'black') do
179
+ safe_join([
180
+ tag.path(d: 'M14.463 13.831c-1.753 1.294-4.291 1.981-6.478 1.981-3.066 0-5.825-1.131-7.912-3.019-.163-.147-.019-.35.178-.234 2.253 1.313 5.041 2.1 7.919 2.1 1.941 0 4.075-.403 6.041-1.238.294-.125.544.197.253.409z'),
181
+ tag.path(d: 'M15.191 13c-.225-.287-1.481-.137-2.047-.069-.172.019-.197-.128-.044-.238 1.003-.703 2.647-.5 2.838-.266.194.238-.05 1.884-.991 2.672-.144.122-.281.056-.219-.103.216-.528.688-1.709.463-1.997zM11.053 11.838l.003.003c.387-.341 1.084-.95 1.478-1.278.156-.125.128-.334.006-.509-.353-.488-.728-.884-.728-1.784v-3c0-1.272.088-2.438-.847-3.313-.738-.706-1.963-.956-2.9-.956-1.831 0-3.875.684-4.303 2.947-.047.241.131.369.287.403l1.866.203c.175-.009.3-.181.334-.356.159-.778.813-1.156 1.547-1.156.397 0 .847.144 1.081.5.269.397.234.938.234 1.397v.25c-1.116.125-2.575.206-3.619.666-1.206.522-2.053 1.584-2.053 3.147 0 2 1.259 3 2.881 3 1.369 0 2.116-.322 3.172-1.403.35.506.463.753 1.103 1.284a.395.395 0 0 0 .456-.044zm-1.94-4.694c0 .75.019 1.375-.359 2.041-.306.544-.791.875-1.331.875-.737 0-1.169-.563-1.169-1.394 0-1.641 1.472-1.938 2.863-1.938v.416z')
182
+ ])
183
+ end
184
+ end
185
+ end
186
+
187
+ def microsoft_icon(size_class)
188
+ tag.svg(aria_label: 'Microsoft logo', class: size_class, xmlns: 'http://www.w3.org/2000/svg',
189
+ viewBox: '0 0 512 512') do
190
+ safe_join([
191
+ tag.path(d: 'M96 96H247V247H96', fill: '#f24f23'),
192
+ tag.path(d: 'M265 96V247H416V96', fill: '#7eba03'),
193
+ tag.path(d: 'M96 265H247V416H96', fill: '#3ca4ef'),
194
+ tag.path(d: 'M265 265H416V416H265', fill: '#f9ba00')
195
+ ])
196
+ end
197
+ end
198
+
199
+ def line_icon(size_class)
200
+ tag.svg(aria_label: 'Line logo', class: size_class, xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 16 16') do
201
+ tag.g(fill_rule: 'evenodd', stroke_linejoin: 'round', fill: 'white') do
202
+ tag.path(fill_rule: 'nonzero',
203
+ d: 'M12.91 6.57c.232 0 .42.19.42.42 0 .23-.188.42-.42.42h-1.17v.75h1.17a.42.42 0 1 1 0 .84h-1.59a.42.42 0 0 1-.418-.42V5.4c0-.23.188-.42.42-.42h1.59a.42.42 0 0 1-.002.84h-1.17v.75h1.17zm-2.57 2.01a.421.421 0 0 1-.757.251l-1.63-2.217V8.58a.42.42 0 0 1-.42.42.42.42 0 0 1-.418-.42V5.4a.418.418 0 0 1 .755-.249L9.5 7.366V5.4c0-.23.188-.42.42-.42.23 0 .42.19.42.42v3.18zm-3.828 0c0 .23-.188.42-.42.42a.42.42 0 0 1-.418-.42V5.4c0-.23.188-.42.42-.42.23 0 .418.19.418.42v3.18zM4.868 9h-1.59c-.23 0-.42-.19-.42-.42V5.4c0-.23.19-.42.42-.42.232 0 .42.19.42.42v2.76h1.17a.42.42 0 1 1 0 .84M16 6.87C16 3.29 12.41.376 8 .376S0 3.29 0 6.87c0 3.208 2.846 5.896 6.69 6.405.26.056.615.172.705.394.08.2.053.518.026.722 0 0-.092.565-.113.685-.035.203-.16.79.693.432.854-.36 4.607-2.714 6.285-4.646C15.445 9.594 16 8.302 16 6.87')
204
+ end
205
+ end
206
+ end
207
+
208
+ def metamask_icon(size_class)
209
+ tag.svg(aria_label: 'MetaMask logo', class: size_class, xmlns: 'http://www.w3.org/2000/svg',
210
+ viewBox: '0 0 507.83 470.86') do
211
+ tag.defs do
212
+ tag.style('.b{fill:#e4761b;stroke:#e4761b}.c{fill:#d7c1b3;stroke:#d7c1b3}.d{fill:#233447;stroke:#233447}.e{fill:#cd6116;stroke:#cd6116}.f{fill:#e4751f;stroke:#e4751f}.g{fill:#f6851b;stroke:#f6851b}.j{fill:#763d16;stroke:#763d16}.b,.c,.d,.e,.f,.g,.j{stroke-linecap:round;stroke-linejoin:round}')
213
+ end
214
+ safe_join([
215
+ tag.path(d: 'M482.09.5 284.32 147.38l36.58-86.66z',
216
+ style: 'fill:#e2761b;stroke:#e2761b;stroke-linecap:round;stroke-linejoin:round'),
217
+ tag.path(
218
+ d: 'm25.54.5 196.18 148.27-34.79-88.05zM410.93 340.97l-52.67 80.7 112.7 31 32.4-109.91zM4.67 342.76l32.2 109.91 112.7-31-52.67-80.7z', class: 'b'
219
+ ),
220
+ tag.path(
221
+ d: 'm143.21 204.62-31.41 47.51 111.9 4.97-3.97-120.25zM364.42 204.62l-77.51-69.16-2.59 121.64 111.71-4.97zM149.57 421.67l67.18-32.8-58.04-45.32zM290.88 388.87l67.38 32.8-9.34-78.12z', class: 'b'
222
+ ),
223
+ tag.path(
224
+ d: 'm358.26 421.67-67.38-32.8 5.37 43.93-.6 18.48zM149.57 421.67l62.61 29.61-.4-18.48 4.97-43.93z', class: 'c'
225
+ ),
226
+ tag.path(d: 'm213.17 314.54-56.05-16.5 39.55-18.09zM294.46 314.54l16.5-34.59 39.75 18.09z',
227
+ class: 'd'),
228
+ tag.path(
229
+ d: 'm149.57 421.67 9.54-80.7-62.21 1.79zM348.72 340.97l9.54 80.7 52.67-78.91zM396.03 252.13l-111.71 4.97 10.34 57.44 16.5-34.59 39.75 18.09zM157.12 298.04l39.75-18.09 16.3 34.59 10.53-57.44-111.9-4.97z', class: 'e'
230
+ ),
231
+ tag.path(
232
+ d: 'm111.8 252.13 46.91 91.42-1.59-45.51zM350.91 298.04l-1.99 45.51 47.11-91.42zM223.7 257.1l-10.53 57.44 13.12 67.77 2.98-89.24zM284.32 257.1l-5.36 35.77 2.38 89.44 13.32-67.77z', class: 'f'
233
+ ),
234
+ tag.path(
235
+ d: 'm294.66 314.54-13.32 67.77 9.54 6.56 58.04-45.32 1.99-45.51zM157.12 298.04l1.59 45.51 58.04 45.32 9.54-6.56-13.12-67.77z', class: 'g'
236
+ ),
237
+ tag.path(
238
+ d: 'M295.65 451.28l.6-18.48-4.97-4.38h-74.93l-4.57 4.38.4 18.48-62.61-29.61 21.86 17.88 44.32 30.81h76.13l44.52-30.81 21.86-17.88z', style: 'stroke-linecap:round;stroke-linejoin:round;fill:#c0ad9e;stroke:#c0ad9e'
239
+ ),
240
+ tag.path(d: 'm290.88 388.87-9.54-6.56h-55.05l-9.54 6.56-4.97 43.93 4.57-4.38h74.93l4.97 4.38z',
241
+ style: 'stroke-linecap:round;stroke-linejoin:round;fill:#161616;stroke:#161616'),
242
+ tag.path(
243
+ d: 'M490.44 156.92l16.89-81.09L482.09.5 290.88 142.41l73.54 62.21 103.95 30.41 23.06-26.83-9.94-7.15 15.9-14.51-12.32-9.54 15.9-12.13zM.5 75.83l16.89 81.09-10.73 7.95L22.56 177l-12.12 9.54 15.9 14.51-9.94 7.15 22.86 26.83 103.95-30.41 73.54-62.21L25.54.5z', class: 'j'
244
+ ),
245
+ tag.path(
246
+ d: 'm468.37 235.03-103.95-30.41 31.61 47.51-47.11 91.42 62.01-.79h92.43zM143.21 204.62 39.26 235.03 4.67 342.76H96.9l61.81.79-46.91-91.42zM284.32 257.1l6.56-114.69 30.22-81.69H186.93l29.82 81.69 6.95 114.69 2.39 36.17.2 89.04h55.05l.4-89.04z', class: 'g'
247
+ )
248
+ ])
249
+ end
250
+ end
251
+
252
+ def slack_icon(size_class)
253
+ tag.svg(aria_label: 'Slack logo', class: size_class, xmlns: 'http://www.w3.org/2000/svg',
254
+ viewBox: '0 0 512 512') do
255
+ tag.g(stroke_linecap: 'round', stroke_width: '78') do
256
+ safe_join([
257
+ tag.path(stroke: '#36c5f0', d: 'm110 207h97m0-97h.1v-.1'),
258
+ tag.path(stroke: '#2eb67d', d: 'm305 110v97m97 0v.1h.1'),
259
+ tag.path(stroke: '#ecb22e', d: 'm402 305h-97m0 97h-.1v.1'),
260
+ tag.path(stroke: '#e01e5a', d: 'M110 305h.1v.1m97 0v97')
261
+ ])
262
+ end
263
+ end
264
+ end
265
+
266
+ def linkedin_icon(size_class)
267
+ tag.svg(aria_label: 'LinkedIn logo', class: size_class, xmlns: 'http://www.w3.org/2000/svg',
268
+ viewBox: '0 0 32 32') do
269
+ tag.path(fill: 'white', fill_rule: 'evenodd',
270
+ d: 'M26.111,3H5.889c-1.595,0-2.889,1.293-2.889,2.889V26.111c0,1.595,1.293,2.889,2.889,2.889H26.111c1.595,0,2.889-1.293,2.889-2.889V5.889c0-1.595-1.293-2.889-2.889-2.889ZM10.861,25.389h-3.877V12.87h3.877v12.519Zm-1.957-14.158c-1.267,0-2.293-1.034-2.293-2.31s1.026-2.31,2.293-2.31,2.292,1.034,2.292,2.31-1.026,2.31-2.292,2.31Zm16.485,14.158h-3.858v-6.571c0-1.802-.685-2.809-2.111-2.809-1.551,0-2.362,1.048-2.362,2.809v6.571h-3.718V12.87h3.718v1.686s1.118-2.069,3.775-2.069,4.556,1.621,4.556,4.975v7.926Z')
271
+ end
272
+ end
273
+
274
+ def vk_icon(size_class)
275
+ tag.svg(aria_label: 'VK logo', class: size_class, xmlns: 'http://www.w3.org/2000/svg',
276
+ viewBox: '0 0 2240 2240') do
277
+ tag.g(fill: 'white') do
278
+ tag.path(d: 'M2077 904q23 64-150 294-24 32-65 85-78 100-90 131-17 41 14 81 17 21 81 82h1l1 1 1 1 2 2q141 131 191 221 3 5 6.5 12.5t7 26.5-.5 34-25 27.5-59 12.5l-256 4q-24 5-56-5t-52-22l-20-12q-30-21-70-64t-68.5-77.5-61-58-56.5-15.5q-3 1-8 3.5t-17 14.5-21.5 29.5-17 52-6.5 77.5q0 15-3.5 27.5t-7.5 18.5l-4 5q-18 19-53 22h-115q-71 4-146-16.5t-131.5-53-103-66T648 1722l-25-24q-10-10-27.5-30t-71.5-91-106-151-122.5-211T165 943q-6-16-6-27t3-16l4-6q15-19 57-19l274-2q12 2 23 6.5t16 8.5l5 3q16 11 24 32 20 50 46 103.5t41 81.5l16 29q29 60 56 104t48.5 68.5T814 1348t34 14 27-5q2-1 5-5t12-22 13.5-47 9.5-81 0-125q-2-40-9-73t-14-46l-6-12q-25-34-85-43-13-2 5-24 17-19 38-30 53-26 239-24 82 1 135 13 20 5 33.5 13.5t20.5 24 10.5 32 3.5 45.5-1 55-2.5 70.5-1.5 82.5q0 11-1 42t-.5 48 3.5 40.5 11.5 39 22.5 24.5q8 2 17 4t26-11 38-34.5 52-67 68-107.5q60-104 107-225 4-10 10-17.5t11-10.5l4-3 5-2.5 13-3 20-.5 288-2q39-5 64 2.5t31 16.5z')
279
+ end
280
+ end
281
+ end
282
+
283
+ def wechat_icon(size_class)
284
+ tag.svg(aria_label: 'WeChat logo', class: size_class, xmlns: 'http://www.w3.org/2000/svg',
285
+ viewBox: '0 0 32 32') do
286
+ tag.g(fill: 'white') do
287
+ safe_join([
288
+ tag.path(d: 'M11.606,3.068C5.031,3.068,0,7.529,0,12.393s4.344,7.681,4.344,7.681l-.706,2.676c-.093,.353,.284,.644,.602,.464l3.173-1.798c1.403,.447,4.381,.59,4.671,.603-.208-.721-.311-1.432-.311-2.095,0-3.754,3.268-9.04,10.532-9.04,.165,0,.331,.004,.496,.011-.965-4.627-5.769-7.827-11.195-7.827Zm-4.327,7.748c-.797,0-1.442-.646-1.442-1.442s.646-1.442,1.442-1.442,1.442,.646,1.442,1.442-.646,1.442-1.442,1.442Zm8.386,0c-.797,0-1.442-.646-1.442-1.442s.646-1.442,1.442-1.442,1.442,.646,1.442,1.442-.646,1.442-1.442,1.442Z'),
289
+ tag.path(d: 'M32,19.336c0-4.26-4.998-7.379-9.694-7.379-6.642,0-9.459,4.797-9.459,7.966s2.818,7.966,9.459,7.966c1.469,0,2.762-.211,3.886-.584l2.498,1.585c.197,.125,.447-.052,.394-.279l-.567-2.46c2.36-1.643,3.483-4.234,3.483-6.815Zm-12.73-.81c-.704,0-1.275-.571-1.275-1.275s.571-1.275,1.275-1.275,1.275,.571,1.275,1.275c0,.705-.571,1.275-1.275,1.275Zm6.373,0c-.704,0-1.275-.571-1.275-1.275s.571-1.275,1.275-1.275,1.275,.571,1.275,1.275-.571,1.275-1.275,1.275Z')
290
+ ])
291
+ end
292
+ end
293
+ end
294
+ end
295
+ end
296
+ # rubocop:enable Layout/LineLength,Metrics/ModuleLength,Metrics/MethodLength,Metrics/AbcSize,Metrics/BlockLength
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Daisy components</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= yield :head %>
9
+
10
+ <%= stylesheet_link_tag "daisy_ui/application", media: "all" %>
11
+ </head>
12
+ <body>
13
+
14
+ <%= yield %>
15
+
16
+ </body>
17
+ </html>
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require 'nokogiri'
6
+ require 'terminal-table'
7
+
8
+ def parse_coverage(xml_path) # rubocop:disable Metrics/AbcSize
9
+ doc = Nokogiri::XML(File.read(xml_path))
10
+ workspace_path = doc.at_xpath('//source').text
11
+ results = {}
12
+
13
+ doc.xpath('//class').each do |klass|
14
+ filename = klass.attr('filename')
15
+ next unless filename # Skip if no filename
16
+
17
+ uncovered_lines = klass.xpath('.//line').select { |line| line.attr('hits') == '0' }
18
+ next if uncovered_lines.empty? # Skip if all lines are covered
19
+
20
+ file_content = File.read(File.join(workspace_path, filename)).split("\n")
21
+ results[filename] = uncovered_lines.map do |line|
22
+ line_number = line.attr('number').to_i
23
+ {
24
+ line_number: line_number,
25
+ content: file_content[line_number - 1]&.strip
26
+ }
27
+ end
28
+ end
29
+
30
+ results
31
+ end
32
+
33
+ def print_results(results)
34
+ return puts 'All lines are covered!' if results.empty?
35
+
36
+ results.each do |filename, uncovered_lines|
37
+ puts "\n\e[33mUncovered lines in #{filename}:\e[0m"
38
+
39
+ rows = uncovered_lines.map do |line|
40
+ [line[:line_number], line[:content]]
41
+ end
42
+
43
+ table = Terminal::Table.new(
44
+ headings: %w[Line Content],
45
+ rows: rows,
46
+ style: { border_x: '-', border_i: '+', alignment: :left }
47
+ )
48
+ puts table
49
+ end
50
+ end
51
+
52
+ coverage_file = ARGV[0] || 'coverage/coverage.xml'
53
+ unless File.exist?(coverage_file)
54
+ puts "\e[31mError: Coverage file not found at #{coverage_file}\e[0m"
55
+ exit 1
56
+ end
57
+
58
+ results = parse_coverage(coverage_file)
59
+ print_results(results)
data/bin/rails ADDED
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # This command will automatically be run when you run "rails" with Rails gems
5
+ # installed from the root of your application.
6
+
7
+ ENGINE_ROOT = File.expand_path('..', __dir__)
8
+ ENGINE_PATH = File.expand_path('../lib/daisy_ui/engine', __dir__)
9
+ APP_PATH = File.expand_path('../test/dummy/config/application', __dir__)
10
+
11
+ # Set up gems listed in the Gemfile.
12
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
13
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
14
+
15
+ if ENV['COVERAGE'] == 'true'
16
+ require 'simplecov'
17
+ require 'simplecov-cobertura'
18
+ SimpleCov.start do
19
+ enable_coverage :branch
20
+ add_filter '/lib/'
21
+ add_filter '/test/controllers/'
22
+ add_filter '/test/dummy/'
23
+ add_filter '/test/fixtures/'
24
+ add_filter '/test/helpers/'
25
+ add_filter '/test/integration/'
26
+ add_filter '/test/mailers/'
27
+ add_filter '/test/models/'
28
+ add_filter '/test/support/'
29
+ add_filter '/test/test_helper.rb'
30
+ add_filter '/test/daisy_ui_test.rb'
31
+ add_filter '/app/helpers/'
32
+ add_group 'Components', 'app/components'
33
+ add_group 'Previews', 'test/components/previews'
34
+
35
+ formatters = [
36
+ SimpleCov::Formatter::CoberturaFormatter,
37
+ SimpleCov::Formatter::HTMLFormatter
38
+ ]
39
+ formatter SimpleCov::Formatter::MultiFormatter.new(formatters)
40
+ end
41
+ puts 'required simplecov'
42
+ end
43
+
44
+ require 'rails'
45
+ # Pick the frameworks you want:
46
+ require 'active_model/railtie'
47
+ require 'active_job/railtie'
48
+ # require "active_record/railtie"
49
+ # require "active_storage/engine"
50
+ require 'action_controller/railtie'
51
+ # require "action_mailer/railtie"
52
+ # require "action_mailbox/engine"
53
+ # require "action_text/engine"
54
+ require 'action_view/railtie'
55
+ # require "action_cable/engine"
56
+ require 'rails/test_unit/railtie'
57
+ require 'rails/engine/commands'
data/bin/rubocop ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'rubygems'
5
+ require 'bundler/setup'
6
+
7
+ # explicit rubocop config increases performance slightly while avoiding config confusion.
8
+ ARGV.unshift('--config', File.expand_path('../.rubocop.yml', __dir__))
9
+
10
+ load Gem.bin_path('rubocop', 'rubocop')
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'nokogiri'
6
+ require 'net/http'
7
+ require 'fileutils'
8
+ require 'optparse'
9
+
10
+ def sanitize_filename(name)
11
+ name.downcase.gsub(/[^a-z0-9]+/, '_')
12
+ end
13
+
14
+ def format_title(id)
15
+ # Convert kebab-case to title case
16
+ id.split('-').map(&:capitalize).join(' ')
17
+ end
18
+
19
+ def scrape_component(component_name)
20
+ url = URI("https://daisyui.com/components/#{component_name}/")
21
+
22
+ puts "Scraping #{url}..."
23
+ response = Net::HTTP.get(url)
24
+ doc = Nokogiri::HTML(response)
25
+
26
+ puts "\n=== PAGE CONTENT ==="
27
+ puts doc.to_html
28
+ puts "=== END PAGE CONTENT ===\n\n"
29
+
30
+ # Create fixtures directory
31
+ fixture_dir = File.expand_path("../test/fixtures/components/#{component_name}", __dir__)
32
+ FileUtils.mkdir_p(fixture_dir)
33
+
34
+ # Find all sections with examples
35
+ sections = []
36
+ doc.css('.component-preview').each do |preview|
37
+ title = preview['id']
38
+ next unless title
39
+
40
+ # Get the code example
41
+ code = preview.css('pre code').first&.text&.gsub('$$', '')
42
+ next unless code && !code.empty?
43
+
44
+ sections << {
45
+ title: format_title(title),
46
+ code: code.strip
47
+ }
48
+ end
49
+
50
+ puts "\nFound #{sections.count} examples"
51
+
52
+ sections.each do |section|
53
+ puts "\n=== Example: #{section[:title]} ==="
54
+ puts "Content preview:"
55
+ puts section[:code][0..100]
56
+
57
+ # Save to fixture file
58
+ filename = "#{sanitize_filename(section[:title])}.html"
59
+ full_path = File.join(fixture_dir, filename)
60
+ File.write(full_path, section[:code])
61
+ puts "\nCreated fixture: #{filename}"
62
+ puts "Full path: #{full_path}"
63
+ end
64
+
65
+ puts "\nDone! Fixtures created in test/fixtures/components/#{component_name}/"
66
+ end
67
+
68
+ # Parse command line arguments
69
+ options = {}
70
+ OptionParser.new do |opts|
71
+ opts.banner = "Usage: #{File.basename(__FILE__)} COMPONENT_NAME"
72
+
73
+ opts.on("-h", "--help", "Show this help message") do
74
+ puts opts
75
+ exit
76
+ end
77
+ end.parse!
78
+
79
+ if ARGV.empty?
80
+ puts "Error: Component name is required"
81
+ puts "Usage: #{File.basename(__FILE__)} COMPONENT_NAME"
82
+ exit 1
83
+ end
84
+
85
+ component_name = ARGV[0]
86
+ scrape_component(component_name)
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/daisy_ui/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'daisy_components'
7
+ spec.version = DaisyUI::VERSION
8
+ spec.authors = ['Patrick Barattin']
9
+ spec.email = ['p.barattin@gmail.com']
10
+ spec.homepage = 'https://github.com/Nittarab/daisy_components'
11
+ spec.summary = 'DaisyUI components for Rails'
12
+ spec.description = 'A collection of ViewComponents implementing DaisyUI design system'
13
+ spec.license = 'MIT'
14
+ spec.required_ruby_version = '>= 3.4.0'
15
+
16
+ spec.metadata['homepage_uri'] = spec.homepage
17
+ spec.metadata['source_code_uri'] = 'https://github.com/Nittarab/daisy_components'
18
+ spec.metadata['changelog_uri'] = 'https://github.com/Nittarab/daisy_components/blob/main/CHANGELOG.md'
19
+
20
+ # Use git to list files and then filter to include only necessary directories and top-level files.
21
+ # This is often more reliable than Dir.glob, especially in complex build environments.
22
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
23
+ # Reject files/directories starting with specific prefixes (test, spec, tmp, .*)
24
+ # or specific files like .rubocop.yml
25
+ f.match(%r{^(test|spec|tmp|\.|Gemfile\.lock|\.rubocop\.yml)/}) || f == '.rubocop.yml'
26
+ end
27
+
28
+ spec.add_dependency 'rails', '>= 8.0.1'
29
+ spec.metadata['rubygems_mfa_required'] = 'true'
30
+
31
+ # This tells Bundler what file to require when the gem is loaded
32
+ spec.require_paths = ['lib']
33
+ end
Binary file
Binary file
Binary file
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file is the entry point for the daisy_components gem
4
+ # It loads the DaisyUI namespace and engine
5
+ require 'daisy_ui'
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaisyUI
4
+ class Engine < ::Rails::Engine
5
+ isolate_namespace DaisyUI
6
+
7
+ # Configure inflector for proper constant mapping
8
+ config.before_initialize do
9
+ Rails.autoloaders.each do |autoloader|
10
+ autoloader.inflector.inflect(
11
+ 'daisy_ui' => 'DaisyUI'
12
+ )
13
+
14
+ # Collapse directories to avoid nested namespaces
15
+ autoloader.collapse(root.join('app/components/daisy_ui/actions'))
16
+ autoloader.collapse(root.join('app/components/daisy_ui/data_display'))
17
+ end
18
+ end
19
+
20
+ # Only load Lookbook in development
21
+ if Rails.env.development?
22
+ initializer 'daisyui.lookbook' do |_app|
23
+ # Configure Lookbook paths relative to the engine
24
+ Lookbook.configure do |config|
25
+ # Initialize paths as arrays before appending
26
+ config.preview_paths = [root.join('test/components/previews')]
27
+ config.layout_paths = [root.join('test/components/previews/layouts')]
28
+ config.page_paths = [root.join('test/components/docs')]
29
+
30
+ # Group components by their namespace
31
+ config.preview_nav_groups = {
32
+ 'Actions' => 'daisyui/actions/*',
33
+ 'Data Display' => 'daisyui/data_display/*',
34
+ 'Data Input' => 'daisyui/data_input/*',
35
+ 'Layout' => 'daisyui/layout/*',
36
+ 'Navigation' => 'daisyui/navigation/*'
37
+ }
38
+
39
+ # Configure the default display options
40
+ config.display_options = {
41
+ theme: 'light',
42
+ bg_color: '#ffffff',
43
+ padding: true
44
+ }
45
+ end
46
+ end
47
+
48
+ config.autoload_paths << root.join('app/components')
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DaisyUI
4
+ VERSION = '0.1.0'
5
+ end
data/lib/daisy_ui.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'daisy_ui/version'
4
+ require 'daisy_ui/engine'
5
+ require 'view_component'
6
+
7
+ # Only require lookbook in development
8
+ require 'lookbook' if Rails.env.development?
9
+
10
+ module DaisyUI
11
+ class Error < StandardError; end
12
+ # Your code goes here...
13
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # desc "Explaining what the task does"
4
+ # task :daisy_ui do
5
+ # # Task goes here
6
+ # end