iron-cms 0.4.5 → 0.5.1

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +3 -0
  3. data/app/assets/builds/iron.css +1154 -1395
  4. data/app/assets/tailwind/iron/application.css +3 -1
  5. data/app/assets/tailwind/iron/components/badge.css +97 -0
  6. data/app/assets/tailwind/iron/components/form.css +1 -1
  7. data/app/assets/tailwind/iron/components/input.css +2 -2
  8. data/app/assets/tailwind/iron/lexxy.css +366 -0
  9. data/app/controllers/iron/home_controller.rb +1 -0
  10. data/app/helpers/iron/application_helper.rb +4 -13
  11. data/app/helpers/iron/entries_helper.rb +0 -4
  12. data/app/helpers/iron/icons_helper.rb +7 -5
  13. data/app/helpers/iron/ui_helper.rb +22 -0
  14. data/app/javascript/iron/application.js +5 -3
  15. data/app/views/iron/block_definitions/_block_definition.html.erb +2 -2
  16. data/app/views/iron/content_types/_content_type.html.erb +2 -2
  17. data/app/views/iron/content_types/show.html.erb +1 -1
  18. data/app/views/iron/entries/fields/_rich_text_area.html.erb +1 -3
  19. data/app/views/iron/field_definitions/_field_definition.html.erb +2 -4
  20. data/app/views/iron/home/show.html.erb +48 -2
  21. data/app/views/iron/locales/_locale.html.erb +1 -1
  22. data/app/views/iron/users/_user.html.erb +1 -1
  23. data/app/views/layouts/action_text/contents/_content.html.erb +1 -1
  24. data/app/views/layouts/iron/_sidebar_content.html.erb +30 -6
  25. data/app/views/layouts/iron/_user_menu.html.erb +1 -1
  26. data/app/views/layouts/iron/authentication.html.erb +1 -1
  27. data/config/importmap.rb +2 -2
  28. data/lib/iron/engine.rb +2 -0
  29. data/lib/iron/version.rb +1 -1
  30. data/lib/iron.rb +0 -1
  31. data/lib/puma/plugin/iron_tailwindcss.rb +8 -8
  32. data/lib/tasks/iron_tailwindcss.rake +33 -0
  33. data/vendor/javascript/lexxy.js +10814 -0
  34. metadata +20 -8
  35. data/app/assets/tailwind/iron/actiontext.css +0 -550
  36. data/app/helpers/iron/block_helper.rb +0 -4
  37. data/app/helpers/iron/buttons_helper.rb +0 -14
  38. data/app/helpers/iron/components/badge_helper.rb +0 -70
  39. data/app/javascript/iron/controllers/trix_controller.js +0 -19
  40. data/lib/iron/cva.rb +0 -69
  41. data/vendor/javascript/trix.js +0 -5
@@ -3,17 +3,19 @@
3
3
  @source "../../../views/**/*.erb";
4
4
  @source "../../../helpers/**/*.rb";
5
5
  @source "../../../javascript/**/*.js";
6
+ @source "./**/*.css";
6
7
 
7
8
  @import './components/input.css';
8
9
  @import './components/textarea.css';
9
10
  @import './components/button.css';
11
+ @import './components/badge.css';
10
12
  @import './components/dropdown.css';
11
13
  @import './components/fieldset.css';
12
14
  @import './components/page.css';
13
15
  @import './components/sidebar.css';
14
16
  @import './components/form.css';
15
17
  @import './components/icon-picker.css';
16
- @import './actiontext.css';
18
+ @import './lexxy.css';
17
19
 
18
20
  @plugin '@tailwindcss/typography';
19
21
 
@@ -0,0 +1,97 @@
1
+ /* Base badge styles with default stone color */
2
+ @utility badge {
3
+ @apply inline-flex items-center gap-x-1.5 rounded-md px-1.5 py-0.5 text-sm/5 font-medium sm:text-xs/5 forced-colors:outline;
4
+ @apply bg-stone-600/10 text-stone-700 group-hover:bg-stone-600/20;
5
+ @apply dark:bg-white/5 dark:text-stone-400 dark:group-hover:bg-white/10;
6
+ }
7
+
8
+ /* Color variants */
9
+ @utility badge-stone {
10
+ @apply bg-stone-600/10 text-stone-700 group-hover:bg-stone-600/20;
11
+ @apply dark:bg-white/5 dark:text-stone-400 dark:group-hover:bg-white/10;
12
+ }
13
+
14
+ @utility badge-red {
15
+ @apply bg-red-500/15 text-red-700 group-hover:bg-red-500/25;
16
+ @apply dark:bg-red-500/10 dark:text-red-400 dark:group-hover:bg-red-500/20;
17
+ }
18
+
19
+ @utility badge-orange {
20
+ @apply bg-orange-500/15 text-orange-700 group-hover:bg-orange-500/25;
21
+ @apply dark:bg-orange-500/10 dark:text-orange-400 dark:group-hover:bg-orange-500/20;
22
+ }
23
+
24
+ @utility badge-amber {
25
+ @apply bg-amber-400/20 text-amber-700 group-hover:bg-amber-400/30;
26
+ @apply dark:bg-amber-400/10 dark:text-amber-400 dark:group-hover:bg-amber-400/15;
27
+ }
28
+
29
+ @utility badge-yellow {
30
+ @apply bg-yellow-400/20 text-yellow-700 group-hover:bg-yellow-400/30;
31
+ @apply dark:bg-yellow-400/10 dark:text-yellow-300 dark:group-hover:bg-yellow-400/15;
32
+ }
33
+
34
+ @utility badge-lime {
35
+ @apply bg-lime-400/20 text-lime-700 group-hover:bg-lime-400/30;
36
+ @apply dark:bg-lime-400/10 dark:text-lime-300 dark:group-hover:bg-lime-400/15;
37
+ }
38
+
39
+ @utility badge-green {
40
+ @apply bg-green-500/15 text-green-700 group-hover:bg-green-500/25;
41
+ @apply dark:bg-green-500/10 dark:text-green-400 dark:group-hover:bg-green-500/20;
42
+ }
43
+
44
+ @utility badge-emerald {
45
+ @apply bg-emerald-500/15 text-emerald-700 group-hover:bg-emerald-500/25;
46
+ @apply dark:bg-emerald-500/10 dark:text-emerald-400 dark:group-hover:bg-emerald-500/20;
47
+ }
48
+
49
+ @utility badge-teal {
50
+ @apply bg-teal-500/15 text-teal-700 group-hover:bg-teal-500/25;
51
+ @apply dark:bg-teal-500/10 dark:text-teal-300 dark:group-hover:bg-teal-500/20;
52
+ }
53
+
54
+ @utility badge-cyan {
55
+ @apply bg-cyan-400/20 text-cyan-700 group-hover:bg-cyan-400/30;
56
+ @apply dark:bg-cyan-400/10 dark:text-cyan-300 dark:group-hover:bg-cyan-400/15;
57
+ }
58
+
59
+ @utility badge-sky {
60
+ @apply bg-sky-500/15 text-sky-700 group-hover:bg-sky-500/25;
61
+ @apply dark:bg-sky-500/10 dark:text-sky-300 dark:group-hover:bg-sky-500/20;
62
+ }
63
+
64
+ @utility badge-blue {
65
+ @apply bg-blue-500/15 text-blue-700 group-hover:bg-blue-500/25;
66
+ @apply dark:text-blue-400 dark:group-hover:bg-blue-500/25;
67
+ }
68
+
69
+ @utility badge-indigo {
70
+ @apply bg-indigo-500/15 text-indigo-700 group-hover:bg-indigo-500/25;
71
+ @apply dark:text-indigo-400 dark:group-hover:bg-indigo-500/20;
72
+ }
73
+
74
+ @utility badge-violet {
75
+ @apply bg-violet-500/15 text-violet-700 group-hover:bg-violet-500/25;
76
+ @apply dark:text-violet-400 dark:group-hover:bg-violet-500/20;
77
+ }
78
+
79
+ @utility badge-purple {
80
+ @apply bg-purple-500/15 text-purple-700 group-hover:bg-purple-500/25;
81
+ @apply dark:text-purple-400 dark:group-hover:bg-purple-500/20;
82
+ }
83
+
84
+ @utility badge-fuchsia {
85
+ @apply bg-fuchsia-400/15 text-fuchsia-700 group-hover:bg-fuchsia-400/25;
86
+ @apply dark:bg-fuchsia-400/10 dark:text-fuchsia-400 dark:group-hover:bg-fuchsia-400/20;
87
+ }
88
+
89
+ @utility badge-pink {
90
+ @apply bg-pink-400/15 text-pink-700 group-hover:bg-pink-400/25;
91
+ @apply dark:bg-pink-400/10 dark:text-pink-400 dark:group-hover:bg-pink-400/20;
92
+ }
93
+
94
+ @utility badge-rose {
95
+ @apply bg-rose-400/15 text-rose-700 group-hover:bg-rose-400/25;
96
+ @apply dark:bg-rose-400/10 dark:text-rose-400 dark:group-hover:bg-rose-400/20;
97
+ }
@@ -4,7 +4,7 @@
4
4
  @apply textarea;
5
5
  }
6
6
 
7
- input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]) {
7
+ input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="hidden"]) {
8
8
  @apply input;
9
9
  }
10
10
  input[type="submit"], input[type="button"], button:not(el-select button) {
@@ -9,10 +9,10 @@
9
9
  @apply bg-white;
10
10
 
11
11
  /* Focus state */
12
- @apply focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600;
12
+ @apply focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-sky-600;
13
13
 
14
14
  /* Dark mode */
15
- @apply dark:bg-white/5 dark:text-white dark:outline-white/10 dark:placeholder:text-stone-500 dark:focus:outline-indigo-500;
15
+ @apply dark:bg-white/5 dark:text-white dark:outline-white/10 dark:placeholder:text-stone-500 dark:focus-visible:outline-sky-600;
16
16
 
17
17
  /* States */
18
18
  @apply disabled:opacity-50;
@@ -0,0 +1,366 @@
1
+ /*
2
+ * Lexxy rich text editor styles for Iron CMS
3
+ * Matches the design system with proper light/dark mode support
4
+ */
5
+
6
+ @layer components {
7
+ /* Editor container */
8
+ lexxy-editor {
9
+ @apply block w-full rounded-md;
10
+ @apply bg-white dark:bg-white/5;
11
+ @apply border border-stone-950/10 dark:border-white/10;
12
+ @apply focus-visible:outline-2 focus-visible:outline-sky-600 dark:focus-visible:outline-sky-500;
13
+ }
14
+
15
+ /* Toolbar */
16
+ lexxy-toolbar {
17
+ @apply flex flex-wrap items-center gap-1 p-2;
18
+ @apply border-b border-stone-950/10 dark:border-white/10;
19
+ @apply bg-stone-50 dark:bg-white/5;
20
+ @apply rounded-t-md;
21
+ }
22
+
23
+ /* Toolbar button groups */
24
+ lexxy-toolbar [data-toolbar-group] {
25
+ @apply flex items-center;
26
+ }
27
+
28
+ lexxy-toolbar [data-toolbar-group]:not(:last-child)::after {
29
+ content: "";
30
+ @apply mx-2 h-5 w-px bg-stone-300 dark:bg-white/20;
31
+ }
32
+
33
+ /* Toolbar buttons */
34
+ lexxy-toolbar button {
35
+ @apply inline-flex items-center justify-center;
36
+ @apply h-8 w-8 rounded-md;
37
+ @apply text-stone-700 dark:text-stone-200;
38
+ @apply hover:bg-stone-200 dark:hover:bg-white/10;
39
+ @apply focus-visible:outline-2 focus-visible:outline-stone-600;
40
+ @apply disabled:opacity-40 disabled:pointer-events-none;
41
+ @apply transition-colors;
42
+ }
43
+
44
+ lexxy-toolbar button[aria-pressed="true"],
45
+ lexxy-toolbar button.active {
46
+ @apply bg-stone-200 text-stone-900;
47
+ @apply dark:bg-white/15 dark:text-white;
48
+ }
49
+
50
+ lexxy-toolbar button svg {
51
+ @apply size-5 text-inherit;
52
+ fill: currentColor;
53
+ }
54
+
55
+ /* Editor content area */
56
+ lexxy-editor [contenteditable] {
57
+ @apply block w-full min-h-48 p-4;
58
+ @apply text-base/6 text-stone-950 dark:text-white;
59
+ @apply outline-none;
60
+ @apply sm:text-sm/6;
61
+ }
62
+
63
+ lexxy-editor [contenteditable]:empty::before {
64
+ content: attr(data-placeholder);
65
+ @apply text-stone-400 dark:text-stone-500;
66
+ @apply pointer-events-none;
67
+ }
68
+
69
+ /* Link dialog/popover */
70
+ lexxy-editor [data-lexxy-link-editor] {
71
+ @apply flex items-center gap-2 p-2;
72
+ @apply bg-white dark:bg-stone-800;
73
+ @apply border border-stone-200 dark:border-white/10;
74
+ @apply rounded-lg shadow-lg;
75
+ @apply focus-visible:outline-2 focus-visible:outline-indigo-600;
76
+ }
77
+
78
+ lexxy-editor [data-lexxy-link-editor] input {
79
+ @apply px-2 py-1 text-sm rounded;
80
+ @apply bg-white dark:bg-white/5;
81
+ @apply border border-stone-300 dark:border-white/10;
82
+ @apply text-stone-900 dark:text-white;
83
+ @apply placeholder:text-stone-400 dark:placeholder:text-stone-500;
84
+ @apply focus-visible:outline-2 focus-visible:outline-indigo-600 dark:focus-visible:outline-indigo-500;
85
+ }
86
+
87
+ lexxy-editor [data-lexxy-link-editor] button {
88
+ @apply px-2 py-1 text-sm font-medium rounded;
89
+ @apply bg-indigo-600 text-white;
90
+ @apply hover:bg-indigo-500;
91
+ }
92
+
93
+ /* Floating link dialog */
94
+ lexxy-link-dialog dialog {
95
+ @apply m-0 p-3;
96
+ @apply rounded-lg border border-stone-200 bg-white shadow-lg;
97
+ @apply dark:border-white/10 dark:bg-stone-800;
98
+ min-width: 18rem;
99
+ }
100
+
101
+ lexxy-link-dialog form {
102
+ @apply flex flex-col gap-3;
103
+ }
104
+
105
+ lexxy-link-dialog button {
106
+ @apply inline-flex items-center justify-center;
107
+ @apply size-auto min-w-0;
108
+ }
109
+
110
+ lexxy-link-dialog input[type="url"] {
111
+ @apply w-full rounded-md;
112
+ @apply border border-stone-300 bg-white px-3 py-2 text-sm text-stone-900;
113
+ @apply placeholder:text-stone-400;
114
+ @apply focus-visible:outline-2 focus-visible:outline-indigo-600;
115
+ @apply dark:border-white/10 dark:bg-stone-900 dark:text-white dark:placeholder:text-stone-500 dark:focus-visible:outline-indigo-500;
116
+ }
117
+
118
+ lexxy-link-dialog .lexxy-dialog-actions {
119
+ @apply flex items-center justify-end gap-2;
120
+ }
121
+
122
+ lexxy-link-dialog .lexxy-dialog-actions button {
123
+ @apply inline-flex items-center justify-center gap-1;
124
+ @apply rounded-md px-3 py-1.5 text-sm font-semibold;
125
+ @apply text-white bg-indigo-600 hover:bg-indigo-500;
126
+ @apply shadow-sm;
127
+ @apply focus-visible:outline-2 focus-visible:outline-indigo-500;
128
+ }
129
+
130
+ lexxy-link-dialog .lexxy-dialog-actions button[value="unlink"] {
131
+ @apply text-stone-800 bg-stone-100 hover:bg-stone-200;
132
+ @apply border border-stone-200;
133
+ @apply dark:text-white dark:bg-white/10 dark:border-white/20 dark:hover:bg-white/15;
134
+ }
135
+
136
+ /* Attachment upload progress */
137
+ lexxy-editor .attachment__progress {
138
+ @apply absolute z-10;
139
+ @apply h-1 top-1/2 left-[5%] w-[90%] -translate-y-1/2;
140
+ @apply bg-stone-200 dark:bg-stone-700 rounded-full overflow-hidden;
141
+ }
142
+
143
+ lexxy-editor .attachment__progress::-webkit-progress-bar {
144
+ @apply bg-stone-200 dark:bg-stone-700;
145
+ }
146
+
147
+ lexxy-editor .attachment__progress::-webkit-progress-value {
148
+ @apply bg-indigo-600;
149
+ @apply transition-all duration-200;
150
+ }
151
+
152
+ lexxy-editor .attachment__progress::-moz-progress-bar {
153
+ @apply bg-indigo-600;
154
+ }
155
+
156
+ lexxy-editor .attachment__progress[value="100"] {
157
+ @apply opacity-0;
158
+ @apply transition-opacity duration-200;
159
+ }
160
+
161
+ /* Attachments in editor */
162
+ lexxy-editor .attachment {
163
+ @apply relative inline-block max-w-full;
164
+ }
165
+
166
+ lexxy-editor .attachment--preview {
167
+ @apply w-full text-center;
168
+ }
169
+
170
+ lexxy-editor .attachment--preview img {
171
+ @apply max-w-full rounded;
172
+ }
173
+
174
+ lexxy-editor .attachment--file {
175
+ @apply inline-flex items-center gap-2;
176
+ @apply px-3 py-2 my-1;
177
+ @apply bg-stone-100 dark:bg-white/10;
178
+ @apply border border-stone-200 dark:border-white/10;
179
+ @apply rounded-lg;
180
+ @apply text-sm text-stone-700 dark:text-stone-300;
181
+ }
182
+
183
+ lexxy-editor .attachment__caption {
184
+ @apply text-center text-sm text-stone-500 dark:text-stone-400;
185
+ @apply mt-1;
186
+ }
187
+
188
+ lexxy-editor .attachment__toolbar {
189
+ @apply absolute z-10 top-2 right-2;
190
+ @apply flex items-center gap-1;
191
+ }
192
+
193
+ lexxy-editor .attachment__toolbar button {
194
+ @apply size-6 rounded-full;
195
+ @apply bg-white/90 dark:bg-stone-800/90;
196
+ @apply text-stone-600 dark:text-stone-400;
197
+ @apply hover:bg-white dark:hover:bg-stone-800;
198
+ @apply shadow-sm;
199
+ }
200
+
201
+ /* Selected attachment state */
202
+ lexxy-editor [data-trix-mutable] img,
203
+ lexxy-editor .attachment.selected img {
204
+ @apply ring-2 ring-indigo-500;
205
+ }
206
+ }
207
+
208
+ /* Rendered content styles */
209
+ @layer components {
210
+ .lexxy-content {
211
+ @apply text-base/7 text-stone-900 dark:text-stone-100;
212
+ @apply break-words;
213
+ }
214
+
215
+ .lexxy-content > * + * {
216
+ @apply mt-4;
217
+ }
218
+
219
+ .lexxy-content p {
220
+ @apply my-0;
221
+ }
222
+
223
+ .lexxy-content p + p {
224
+ @apply mt-4;
225
+ }
226
+
227
+ .lexxy-content strong {
228
+ @apply font-semibold text-stone-950 dark:text-white;
229
+ }
230
+
231
+ .lexxy-content em {
232
+ @apply italic;
233
+ }
234
+
235
+ .lexxy-content a {
236
+ @apply text-indigo-600 dark:text-indigo-400;
237
+ @apply underline underline-offset-2;
238
+ @apply hover:text-indigo-500 dark:hover:text-indigo-300;
239
+ }
240
+
241
+ .lexxy-content h1 {
242
+ @apply text-2xl font-bold text-stone-950 dark:text-white;
243
+ @apply mt-8 mb-4;
244
+ }
245
+
246
+ .lexxy-content h2 {
247
+ @apply text-xl font-bold text-stone-950 dark:text-white;
248
+ @apply mt-6 mb-3;
249
+ }
250
+
251
+ .lexxy-content h3 {
252
+ @apply text-lg font-semibold text-stone-950 dark:text-white;
253
+ @apply mt-5 mb-2;
254
+ }
255
+
256
+ .lexxy-content blockquote {
257
+ @apply pl-4 my-4;
258
+ @apply border-l-4 border-stone-300 dark:border-stone-600;
259
+ @apply text-stone-600 dark:text-stone-400;
260
+ @apply italic;
261
+ }
262
+
263
+ .lexxy-content ul {
264
+ @apply list-disc list-inside my-4;
265
+ }
266
+
267
+ .lexxy-content ol {
268
+ @apply list-decimal list-inside my-4;
269
+ }
270
+
271
+ .lexxy-content li {
272
+ @apply my-1;
273
+ }
274
+
275
+ .lexxy-content li > ul,
276
+ .lexxy-content li > ol {
277
+ @apply ml-4 my-1;
278
+ }
279
+
280
+ .lexxy-content code {
281
+ @apply px-1.5 py-0.5 rounded;
282
+ @apply bg-stone-100 dark:bg-white/10;
283
+ @apply text-sm font-mono;
284
+ @apply text-pink-600 dark:text-pink-400;
285
+ }
286
+
287
+ .lexxy-content pre {
288
+ @apply my-4 p-4 rounded-lg overflow-x-auto;
289
+ @apply bg-stone-900 dark:bg-stone-950;
290
+ @apply text-sm leading-relaxed;
291
+ }
292
+
293
+ .lexxy-content pre code {
294
+ @apply p-0 bg-transparent rounded-none;
295
+ @apply text-stone-100;
296
+ @apply block whitespace-pre;
297
+ }
298
+
299
+ .lexxy-content hr {
300
+ @apply my-8 border-t border-stone-200 dark:border-stone-700;
301
+ }
302
+
303
+ .lexxy-content img {
304
+ @apply max-w-full h-auto rounded-lg;
305
+ @apply my-4;
306
+ }
307
+
308
+ /* Attachment rendering in content */
309
+ .lexxy-content .attachment {
310
+ @apply inline-block max-w-full my-4;
311
+ }
312
+
313
+ .lexxy-content .attachment--preview {
314
+ @apply w-full text-center;
315
+ }
316
+
317
+ .lexxy-content .attachment--file {
318
+ @apply inline-flex items-center gap-2;
319
+ @apply px-3 py-2;
320
+ @apply bg-stone-100 dark:bg-white/10;
321
+ @apply border border-stone-200 dark:border-white/10;
322
+ @apply rounded-lg;
323
+ @apply text-sm text-stone-700 dark:text-stone-300;
324
+ @apply hover:bg-stone-200 dark:hover:bg-white/15;
325
+ @apply transition-colors;
326
+ }
327
+
328
+ .lexxy-content .attachment__caption {
329
+ @apply text-center text-sm text-stone-500 dark:text-stone-400;
330
+ @apply mt-2;
331
+ }
332
+
333
+ .lexxy-content .attachment__name {
334
+ @apply font-medium;
335
+ }
336
+
337
+ .lexxy-content .attachment__size {
338
+ @apply text-stone-500 dark:text-stone-400;
339
+ }
340
+
341
+ .lexxy-content .attachment__name + .attachment__size::before {
342
+ content: " · ";
343
+ }
344
+
345
+ /* Attachment gallery */
346
+ .lexxy-content .attachment-gallery {
347
+ @apply flex flex-wrap gap-2 my-4;
348
+ }
349
+
350
+ .lexxy-content .attachment-gallery .attachment,
351
+ .lexxy-content .attachment-gallery > action-text-attachment {
352
+ @apply flex-1 min-w-[calc(33.333%-0.5rem)] max-w-[calc(33.333%-0.5rem)];
353
+ @apply my-0;
354
+ }
355
+
356
+ .lexxy-content .attachment-gallery.attachment-gallery--2 .attachment,
357
+ .lexxy-content .attachment-gallery.attachment-gallery--2 > action-text-attachment,
358
+ .lexxy-content .attachment-gallery.attachment-gallery--4 .attachment,
359
+ .lexxy-content .attachment-gallery.attachment-gallery--4 > action-text-attachment {
360
+ @apply min-w-[calc(50%-0.25rem)] max-w-[calc(50%-0.25rem)];
361
+ }
362
+
363
+ .lexxy-content action-text-attachment .attachment {
364
+ @apply p-0 max-w-full my-0;
365
+ }
366
+ }
@@ -1,6 +1,7 @@
1
1
  module Iron
2
2
  class HomeController < ApplicationController
3
3
  def show
4
+ @recent_entries = Entry.includes(:content_type, :creator).order(updated_at: :desc).limit(10)
4
5
  end
5
6
  end
6
7
  end
@@ -1,21 +1,12 @@
1
1
  require "tailwind_merge"
2
2
  module Iron
3
3
  module ApplicationHelper
4
- include IconsHelper, AvatarHelper, ButtonsHelper, EntriesHelper, ContentTypesHelper
5
- include Components::BadgeHelper
4
+ include IconsHelper, AvatarHelper, UiHelper, EntriesHelper, ContentTypesHelper
6
5
 
7
- def tw(*classes)
8
- TailwindMerge::Merger.new.merge(classes.reject(&:blank?).compact.join(" "))
9
- end
6
+ TAILWIND_MERGER = TailwindMerge::Merger.new.freeze
10
7
 
11
- def cva(base_classes = "", options = {})
12
- Cva::VariantBuilder.new(
13
- base_classes: base_classes,
14
- variants: options[:variants] || {},
15
- defaults: options[:defaults] || {},
16
- compound_variants: options[:compound_variants] || [],
17
- required: options[:required] || []
18
- )
8
+ def tw(*classes)
9
+ TAILWIND_MERGER.merge(classes.reject(&:blank?).compact.join(" "))
19
10
  end
20
11
 
21
12
  def unique_id
@@ -1,8 +1,4 @@
1
1
  module Iron::EntriesHelper
2
- def entry_fields_for(field, prefix, &)
3
- fields_for "#{prefix}[fields_attributes][#{field.id || unique_id}]", field, &
4
- end
5
-
6
2
  def current_content_page?(content_type)
7
3
  request.path.start_with?(content_type_entries_path(content_type)) || (
8
4
  controller_name == "entries" &&
@@ -2,10 +2,6 @@ module Iron
2
2
  module IconsHelper
3
3
  SPRITE_PATH = "iron/icons/sprite.svg"
4
4
 
5
- def available_icons
6
- IconCatalog.all
7
- end
8
-
9
5
  # Examples
10
6
  # icon "heart" # => 24 px outline heart
11
7
  # icon "trash", class: "text-red-600 hover:text-red-700"
@@ -23,8 +19,14 @@ module Iron
23
19
  viewBox: "0 0 24 24",
24
20
  aria_hidden: "true"
25
21
  ) do
26
- tag.use href: "#{image_path(SPRITE_PATH)}##{name}"
22
+ tag.use href: "#{sprite_image_path}##{name}"
27
23
  end
28
24
  end
25
+
26
+ private
27
+
28
+ def sprite_image_path
29
+ @sprite_image_path ||= image_path(SPRITE_PATH)
30
+ end
29
31
  end
30
32
  end
@@ -0,0 +1,22 @@
1
+ module Iron
2
+ module UiHelper
3
+ def back_button_to(title, url, options = {}, &)
4
+ link_to url,
5
+ class: tw(
6
+ "inline-flex items-center gap-2 text-sm/6 text-stone-500 dark:text-stone-400",
7
+ options.delete(:class)
8
+ ) do
9
+ safe_join([
10
+ icon("chevron-left", class: "size-4"),
11
+ tag.span(title)
12
+ ])
13
+ end
14
+ end
15
+
16
+ def badge(content = nil, **options, &block)
17
+ tag.span class: tw("badge", options.delete(:class)), **options do
18
+ block_given? ? capture(&block) : content
19
+ end
20
+ end
21
+ end
22
+ end
@@ -2,7 +2,9 @@
2
2
  import "@hotwired/turbo-rails";
3
3
  import "controllers";
4
4
 
5
- import "trix"
6
- import "@rails/actiontext"
5
+ import * as ActiveStorage from "@rails/activestorage";
6
+ import "lexxy";
7
7
 
8
- import "@tailwindplus/elements"
8
+ import "@tailwindplus/elements";
9
+
10
+ ActiveStorage.start();
@@ -4,7 +4,7 @@
4
4
  <div class="flex flex-col sm:flex-row sm:items-center sm:gap-8 min-w-0 flex-1">
5
5
  <div class="flex items-center gap-3 shrink-0">
6
6
  <h3 class="text-base font-semibold text-stone-900 dark:text-white truncate"><%= block_definition.name %></h3>
7
- <%= badge block_definition.handle, color: :blue, class: "hidden sm:inline-flex" %>
7
+ <%= badge block_definition.handle, class: "badge-blue hidden sm:inline-flex" %>
8
8
  </div>
9
9
 
10
10
  <% if block_definition.description.present? %>
@@ -14,7 +14,7 @@
14
14
  </div>
15
15
 
16
16
  <div class="absolute right-6 top-1/2 -translate-y-1/2 flex items-center gap-4">
17
- <%= badge block_definition.handle, color: :blue, class: "sm:hidden" %>
17
+ <%= badge block_definition.handle, class: "badge-blue sm:hidden" %>
18
18
  <%= icon "chevron-right", variant: :mini, class: "text-stone-400 dark:text-stone-500" %>
19
19
  </div>
20
20
  <% end %>
@@ -4,7 +4,7 @@
4
4
  <div class="flex flex-col sm:flex-row sm:items-center sm:gap-8 min-w-0 flex-1">
5
5
  <div class="flex items-center gap-3 shrink-0">
6
6
  <h3 class="text-base font-semibold text-stone-900 dark:text-white truncate"><%= content_type.name %></h3>
7
- <%= badge content_type.handle, color: :blue, class: "hidden sm:inline-flex" %>
7
+ <%= badge content_type.handle, class: "badge-blue hidden sm:inline-flex" %>
8
8
  </div>
9
9
 
10
10
  <% if content_type.description.present? %>
@@ -14,7 +14,7 @@
14
14
  </div>
15
15
 
16
16
  <div class="absolute right-6 top-1/2 -translate-y-1/2 flex items-center gap-4">
17
- <%= badge content_type.handle, color: :blue, class: "sm:hidden" %>
17
+ <%= badge content_type.handle, class: "badge-blue sm:hidden" %>
18
18
  <%= icon "chevron-right", class: "text-stone-400 dark:text-stone-500" %>
19
19
  </div>
20
20
  <% end %>
@@ -18,7 +18,7 @@
18
18
  </div>
19
19
  <p class="dark:text-stone-400"><%= @content_type.description %></p>
20
20
  <p class="text-sm text-stone-500 dark:text-stone-400 mt-2">
21
- Type: <%= badge @content_type.single? ? "Single" : "Collection", variant: @content_type.single? ? "blue" : "green" %>
21
+ Type: <%= badge @content_type.single? ? "Single" : "Collection", class: @content_type.single? ? "badge-blue" : "badge-green" %>
22
22
  </p>
23
23
 
24
24
  <ul
@@ -7,7 +7,5 @@
7
7
  <%= builder.hidden_field :type %>
8
8
 
9
9
  <%= builder.label :rich_text, field.definition.name %>
10
- <div data-controller="trix">
11
- <%= builder.rich_textarea :rich_text, class: "input prose prose-stone dark:prose-invert min-h-56 max-w-none" %>
12
- </div>
10
+ <%= builder.rich_textarea :rich_text, class: "prose prose-stone dark:prose-invert min-h-56 max-w-none w-full" %>
13
11
  </div>