railspress-engine 0.1.2 → 1.2.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 (140) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +20 -0
  3. data/README.md +195 -25
  4. data/app/assets/javascripts/railspress/admin.js +39 -0
  5. data/app/assets/javascripts/railspress/markdown_mode.js +343 -0
  6. data/app/assets/stylesheets/application.css +0 -0
  7. data/app/assets/stylesheets/railspress/admin/badges.css +70 -0
  8. data/app/assets/stylesheets/railspress/admin/base.css +25 -0
  9. data/app/assets/stylesheets/railspress/admin/buttons.css +140 -0
  10. data/app/assets/stylesheets/railspress/admin/cards.css +52 -0
  11. data/app/assets/stylesheets/railspress/admin/components/exports.css +55 -0
  12. data/app/assets/stylesheets/railspress/admin/components/focal_point.css +801 -0
  13. data/app/assets/stylesheets/railspress/admin/components/imports.css +144 -0
  14. data/app/assets/stylesheets/railspress/admin/components/lexxy.css +156 -0
  15. data/app/assets/stylesheets/railspress/admin/filters.css +73 -0
  16. data/app/assets/stylesheets/railspress/admin/flash.css +26 -0
  17. data/app/assets/stylesheets/railspress/admin/forms.css +459 -0
  18. data/app/assets/stylesheets/railspress/admin/layout.css +256 -0
  19. data/app/assets/stylesheets/railspress/admin/lists.css +24 -0
  20. data/app/assets/stylesheets/railspress/admin/page.css +111 -0
  21. data/app/assets/stylesheets/railspress/admin/responsive.css +174 -0
  22. data/app/assets/stylesheets/railspress/admin/stats.css +43 -0
  23. data/app/assets/stylesheets/railspress/admin/tables.css +163 -0
  24. data/app/assets/stylesheets/railspress/admin/utilities.css +202 -0
  25. data/app/assets/stylesheets/railspress/admin/variables.css +58 -0
  26. data/app/assets/stylesheets/railspress/application.css +44 -13
  27. data/app/controllers/railspress/admin/base_controller.rb +6 -3
  28. data/app/controllers/railspress/admin/categories_controller.rb +1 -1
  29. data/app/controllers/railspress/admin/cms_transfers_controller.rb +49 -0
  30. data/app/controllers/railspress/admin/content_element_versions_controller.rb +12 -0
  31. data/app/controllers/railspress/admin/content_elements_controller.rb +143 -0
  32. data/app/controllers/railspress/admin/content_groups_controller.rb +69 -0
  33. data/app/controllers/railspress/admin/dashboard_controller.rb +6 -0
  34. data/app/controllers/railspress/admin/entities_controller.rb +157 -0
  35. data/app/controllers/railspress/admin/exports_controller.rb +55 -0
  36. data/app/controllers/railspress/admin/focal_points_controller.rb +100 -0
  37. data/app/controllers/railspress/admin/imports_controller.rb +63 -0
  38. data/app/controllers/railspress/admin/posts_controller.rb +58 -4
  39. data/app/controllers/railspress/admin/prototypes_controller.rb +30 -0
  40. data/app/controllers/railspress/admin/tags_controller.rb +1 -1
  41. data/app/controllers/railspress/application_controller.rb +1 -0
  42. data/app/helpers/railspress/admin_helper.rb +733 -0
  43. data/app/helpers/railspress/application_helper.rb +23 -0
  44. data/app/helpers/railspress/cms_helper.rb +319 -0
  45. data/app/javascript/railspress/controllers/cms_inline_editor_controller.js +147 -0
  46. data/app/javascript/railspress/controllers/content_element_form_controller.js +15 -0
  47. data/app/javascript/railspress/controllers/crop_controller.js +224 -0
  48. data/app/javascript/railspress/controllers/dropzone_controller.js +261 -0
  49. data/app/javascript/railspress/controllers/focal_point_controller.js +124 -0
  50. data/app/javascript/railspress/controllers/image_section_controller.js +94 -0
  51. data/app/javascript/railspress/controllers/index.js +37 -0
  52. data/app/javascript/railspress/index.js +62 -0
  53. data/app/jobs/railspress/export_posts_job.rb +16 -0
  54. data/app/jobs/railspress/import_posts_job.rb +44 -0
  55. data/app/models/concerns/railspress/has_focal_point.rb +242 -0
  56. data/app/models/concerns/railspress/soft_deletable.rb +23 -0
  57. data/app/models/concerns/railspress/taggable.rb +23 -0
  58. data/app/models/railspress/content_element.rb +103 -0
  59. data/app/models/railspress/content_element_version.rb +32 -0
  60. data/app/models/railspress/content_group.rb +39 -0
  61. data/app/models/railspress/export.rb +67 -0
  62. data/app/models/railspress/focal_point.rb +70 -0
  63. data/app/models/railspress/import.rb +65 -0
  64. data/app/models/railspress/post.rb +102 -15
  65. data/app/models/railspress/post_export_processor.rb +162 -0
  66. data/app/models/railspress/post_import_processor.rb +382 -0
  67. data/app/models/railspress/tag.rb +10 -3
  68. data/app/models/railspress/tagging.rb +11 -0
  69. data/app/services/railspress/content_export_service.rb +122 -0
  70. data/app/services/railspress/content_import_service.rb +228 -0
  71. data/app/views/action_text/attachables/_remote_image.html.erb +8 -0
  72. data/app/views/active_storage/blobs/_blob.html.erb +1 -1
  73. data/app/views/layouts/railspress/admin.html.erb +3 -1
  74. data/app/views/railspress/admin/categories/index.html.erb +11 -15
  75. data/app/views/railspress/admin/cms_transfers/show.html.erb +167 -0
  76. data/app/views/railspress/admin/content_element_versions/show.html.erb +42 -0
  77. data/app/views/railspress/admin/content_elements/_form.html.erb +71 -0
  78. data/app/views/railspress/admin/content_elements/_inline_form.html.erb +32 -0
  79. data/app/views/railspress/admin/content_elements/_inline_form_frame.html.erb +6 -0
  80. data/app/views/railspress/admin/content_elements/edit.html.erb +6 -0
  81. data/app/views/railspress/admin/content_elements/index.html.erb +74 -0
  82. data/app/views/railspress/admin/content_elements/new.html.erb +6 -0
  83. data/app/views/railspress/admin/content_elements/show.html.erb +124 -0
  84. data/app/views/railspress/admin/content_groups/_form.html.erb +9 -0
  85. data/app/views/railspress/admin/content_groups/edit.html.erb +6 -0
  86. data/app/views/railspress/admin/content_groups/index.html.erb +42 -0
  87. data/app/views/railspress/admin/content_groups/new.html.erb +6 -0
  88. data/app/views/railspress/admin/content_groups/show.html.erb +92 -0
  89. data/app/views/railspress/admin/dashboard/index.html.erb +36 -1
  90. data/app/views/railspress/admin/entities/_form.html.erb +53 -0
  91. data/app/views/railspress/admin/entities/edit.html.erb +4 -0
  92. data/app/views/railspress/admin/entities/index.html.erb +74 -0
  93. data/app/views/railspress/admin/entities/new.html.erb +4 -0
  94. data/app/views/railspress/admin/entities/show.html.erb +117 -0
  95. data/app/views/railspress/admin/exports/show.html.erb +62 -0
  96. data/app/views/railspress/admin/imports/_instructions.html.erb +56 -0
  97. data/app/views/railspress/admin/imports/show.html.erb +137 -0
  98. data/app/views/railspress/admin/posts/_form.html.erb +102 -28
  99. data/app/views/railspress/admin/posts/_post_row.html.erb +40 -0
  100. data/app/views/railspress/admin/posts/index.html.erb +47 -36
  101. data/app/views/railspress/admin/posts/show.html.erb +55 -19
  102. data/app/views/railspress/admin/prototypes/image_section.html.erb +42 -0
  103. data/app/views/railspress/admin/shared/_dropzone.html.erb +84 -0
  104. data/app/views/railspress/admin/shared/_focal_point_editor.html.erb +102 -0
  105. data/app/views/railspress/admin/shared/_image_section.html.erb +159 -0
  106. data/app/views/railspress/admin/shared/_image_section_compact.html.erb +90 -0
  107. data/app/views/railspress/admin/shared/_image_section_editor.html.erb +171 -0
  108. data/app/views/railspress/admin/shared/_image_section_v2.html.erb +205 -0
  109. data/app/views/railspress/admin/shared/_sidebar.html.erb +73 -5
  110. data/app/views/railspress/admin/tags/index.html.erb +12 -16
  111. data/config/brakeman.ignore +18 -0
  112. data/config/importmap.rb +23 -0
  113. data/config/routes.rb +62 -1
  114. data/db/migrate/20241218000004_create_railspress_post_tags.rb +1 -1
  115. data/db/migrate/20241218000005_create_railspress_imports.rb +21 -0
  116. data/db/migrate/20241218000006_create_railspress_exports.rb +20 -0
  117. data/db/migrate/20241218000007_create_railspress_taggings.rb +20 -0
  118. data/db/migrate/20241218000008_drop_railspress_post_tags.rb +14 -0
  119. data/db/migrate/20241218000010_add_reading_time_to_railspress_posts.rb +5 -0
  120. data/db/migrate/20250105000002_create_railspress_focal_points.rb +20 -0
  121. data/db/migrate/20260206000001_create_railspress_content_groups.rb +18 -0
  122. data/db/migrate/20260206000002_create_railspress_content_elements.rb +21 -0
  123. data/db/migrate/20260206000003_create_railspress_content_element_versions.rb +20 -0
  124. data/db/migrate/20260207000001_add_unique_index_to_content_elements.rb +11 -0
  125. data/db/migrate/20260211112812_add_image_hint_to_railspress_content_elements.rb +7 -0
  126. data/db/migrate/20260211154040_add_required_to_railspress_content_elements.rb +5 -0
  127. data/lib/generators/railspress/entity/entity_generator.rb +89 -0
  128. data/lib/generators/railspress/entity/templates/migration.rb.tt +13 -0
  129. data/lib/generators/railspress/entity/templates/model.rb.tt +21 -0
  130. data/lib/generators/railspress/install/install_generator.rb +51 -40
  131. data/lib/generators/railspress/install/templates/initializer.rb +29 -0
  132. data/lib/railspress/engine.rb +38 -0
  133. data/lib/railspress/entity.rb +239 -0
  134. data/lib/railspress/version.rb +1 -1
  135. data/lib/railspress.rb +198 -8
  136. data/lib/tasks/railspress_tasks.rake +49 -4
  137. metadata +215 -21
  138. data/MIT-LICENSE +0 -20
  139. data/app/assets/stylesheets/railspress/admin.css +0 -1207
  140. data/app/models/railspress/post_tag.rb +0 -8
@@ -0,0 +1,459 @@
1
+ /*
2
+ * RailsPress Admin - Forms
3
+ * Form layouts, inputs, selects, checkboxes
4
+ */
5
+
6
+ /* Form Layout */
7
+ .rp-form {
8
+ display: flex;
9
+ flex-direction: column;
10
+ }
11
+
12
+ .rp-form--narrow {
13
+ max-width: 560px;
14
+ }
15
+
16
+ .rp-form-layout {
17
+ display: grid;
18
+ grid-template-columns: 1fr 280px;
19
+ gap: var(--rp-space-xl);
20
+ align-items: start;
21
+ }
22
+
23
+ .rp-form-main {
24
+ display: flex;
25
+ flex-direction: column;
26
+ gap: var(--rp-space-lg);
27
+ }
28
+
29
+ .rp-form-sidebar {
30
+ display: flex;
31
+ flex-direction: column;
32
+ gap: var(--rp-space-md);
33
+ }
34
+
35
+ .rp-form-group {
36
+ display: flex;
37
+ flex-direction: column;
38
+ gap: 6px;
39
+ }
40
+
41
+ .rp-form-row {
42
+ display: grid;
43
+ grid-template-columns: repeat(2, 1fr);
44
+ gap: var(--rp-space-md);
45
+ }
46
+
47
+ .rp-form-row--3 {
48
+ grid-template-columns: repeat(3, 1fr);
49
+ }
50
+
51
+ .rp-form-actions {
52
+ display: flex;
53
+ gap: var(--rp-space-sm);
54
+ padding-top: var(--rp-space-xl);
55
+ margin-top: var(--rp-space-xl);
56
+ border-top: 1px solid var(--rp-border-light);
57
+ }
58
+
59
+ .rp-form-errors {
60
+ background: var(--rp-danger-light);
61
+ border: 1px solid var(--rp-danger);
62
+ border-radius: var(--rp-radius);
63
+ padding: var(--rp-space-md);
64
+ color: var(--rp-danger);
65
+ font-size: 0.875rem;
66
+ }
67
+
68
+ .rp-form-errors ul {
69
+ margin: 0;
70
+ padding-left: var(--rp-space-lg);
71
+ }
72
+
73
+ /* Labels */
74
+ .rp-label {
75
+ font-size: 0.875rem;
76
+ font-weight: 600;
77
+ color: var(--rp-text);
78
+ }
79
+
80
+ .rp-label--lg {
81
+ font-size: 1rem;
82
+ }
83
+
84
+ .rp-label--required::after {
85
+ content: ' *';
86
+ color: var(--rp-danger);
87
+ }
88
+
89
+ /* Inputs */
90
+ .rp-input {
91
+ width: 100%;
92
+ padding: 10px 12px;
93
+ font-family: var(--rp-font-body);
94
+ font-size: 0.9375rem;
95
+ color: var(--rp-text);
96
+ background: var(--rp-bg-elevated);
97
+ border: 1px solid var(--rp-border);
98
+ border-radius: var(--rp-radius);
99
+ transition: border-color 0.15s, box-shadow 0.15s;
100
+ }
101
+
102
+ .rp-input:focus {
103
+ outline: none;
104
+ border-color: var(--rp-primary);
105
+ box-shadow: 0 0 0 3px var(--rp-primary-light);
106
+ }
107
+
108
+ .rp-input::placeholder {
109
+ color: var(--rp-text-light);
110
+ }
111
+
112
+ .rp-input--sm {
113
+ padding: 6px 10px;
114
+ font-size: 0.875rem;
115
+ }
116
+
117
+ .rp-input--lg {
118
+ padding: 14px 16px;
119
+ font-size: 1.125rem;
120
+ }
121
+
122
+ .rp-input--title {
123
+ font-family: var(--rp-font-display);
124
+ font-size: 1.5rem;
125
+ font-weight: 600;
126
+ padding: 12px 14px;
127
+ letter-spacing: -0.01em;
128
+ }
129
+
130
+ .rp-input--mono {
131
+ font-family: var(--rp-font-mono);
132
+ font-size: 0.875rem;
133
+ }
134
+
135
+ textarea.rp-input {
136
+ min-height: 100px;
137
+ resize: vertical;
138
+ line-height: 1.5;
139
+ }
140
+
141
+ /* Select */
142
+ .rp-select {
143
+ width: 100%;
144
+ padding: 10px 12px;
145
+ padding-right: 36px;
146
+ font-family: var(--rp-font-body);
147
+ font-size: 0.9375rem;
148
+ color: var(--rp-text);
149
+ background: var(--rp-bg-elevated) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%236b6860' d='M6 8L1 3h10z'/%3E%3C/svg%3E") no-repeat right 12px center;
150
+ border: 1px solid var(--rp-border);
151
+ border-radius: var(--rp-radius);
152
+ appearance: none;
153
+ cursor: pointer;
154
+ transition: border-color 0.15s, box-shadow 0.15s;
155
+ }
156
+
157
+ .rp-select:focus {
158
+ outline: none;
159
+ border-color: var(--rp-primary);
160
+ box-shadow: 0 0 0 3px var(--rp-primary-light);
161
+ }
162
+
163
+ .rp-select--sm {
164
+ padding: 6px 10px;
165
+ padding-right: 32px;
166
+ font-size: 0.875rem;
167
+ }
168
+
169
+ /* Checkbox & Radio */
170
+ .rp-checkbox,
171
+ .rp-radio {
172
+ display: flex;
173
+ align-items: flex-start;
174
+ gap: var(--rp-space-sm);
175
+ cursor: pointer;
176
+ }
177
+
178
+ .rp-checkbox input,
179
+ .rp-radio input {
180
+ width: 18px;
181
+ height: 18px;
182
+ margin: 0;
183
+ flex-shrink: 0;
184
+ cursor: pointer;
185
+ accent-color: var(--rp-primary);
186
+ }
187
+
188
+ .rp-checkbox-label,
189
+ .rp-radio-label {
190
+ font-size: 0.9375rem;
191
+ color: var(--rp-text);
192
+ line-height: 1.4;
193
+ }
194
+
195
+ .rp-checkbox-description,
196
+ .rp-radio-description {
197
+ font-size: 0.8125rem;
198
+ color: var(--rp-text-muted);
199
+ margin-top: 2px;
200
+ }
201
+
202
+ .rp-checkbox-group,
203
+ .rp-radio-group {
204
+ display: flex;
205
+ flex-direction: column;
206
+ gap: var(--rp-space-sm);
207
+ }
208
+
209
+ .rp-checkbox-group--inline,
210
+ .rp-radio-group--inline {
211
+ flex-direction: row;
212
+ flex-wrap: wrap;
213
+ gap: var(--rp-space-lg);
214
+ }
215
+
216
+ /* Fieldset */
217
+ .rp-fieldset {
218
+ border: 1px solid var(--rp-border-light);
219
+ border-radius: var(--rp-radius);
220
+ padding: var(--rp-space-lg);
221
+ background: var(--rp-bg);
222
+ }
223
+
224
+ .rp-fieldset-legend {
225
+ font-size: 0.875rem;
226
+ font-weight: 600;
227
+ color: var(--rp-text);
228
+ padding: 0 var(--rp-space-sm);
229
+ margin-left: -var(--rp-space-sm);
230
+ }
231
+
232
+ /* Hint & Help */
233
+ .rp-hint {
234
+ font-size: 0.8125rem;
235
+ color: var(--rp-text-muted);
236
+ margin-top: 4px;
237
+ }
238
+
239
+ .rp-input-wrapper {
240
+ position: relative;
241
+ }
242
+
243
+ .rp-input-prefix,
244
+ .rp-input-suffix {
245
+ position: absolute;
246
+ top: 50%;
247
+ transform: translateY(-50%);
248
+ color: var(--rp-text-muted);
249
+ font-size: 0.9375rem;
250
+ pointer-events: none;
251
+ }
252
+
253
+ .rp-input-prefix {
254
+ left: 12px;
255
+ }
256
+
257
+ .rp-input-suffix {
258
+ right: 12px;
259
+ }
260
+
261
+ .rp-input--has-prefix {
262
+ padding-left: 36px;
263
+ }
264
+
265
+ .rp-input--has-suffix {
266
+ padding-right: 36px;
267
+ }
268
+
269
+ /* Rich text placeholder */
270
+ .rp-rich-text {
271
+ min-height: 670px;
272
+ border: 1px solid var(--rp-border);
273
+ border-radius: var(--rp-radius);
274
+ background: var(--rp-bg-elevated);
275
+ padding: var(--rp-space-md);
276
+ }
277
+
278
+ /* Sidebar sections */
279
+ .rp-sidebar-section {
280
+ background: var(--rp-info-light);
281
+ border-radius: var(--rp-radius);
282
+ padding: var(--rp-space-md);
283
+ border: 1px solid #d8e8f0;
284
+ }
285
+
286
+ .rp-sidebar-section .rp-form-group {
287
+ margin-bottom: var(--rp-space-md);
288
+ }
289
+
290
+ .rp-sidebar-section .rp-form-group:last-child {
291
+ margin-bottom: 0;
292
+ }
293
+
294
+ .rp-sidebar-title {
295
+ font-size: 0.6875rem;
296
+ font-weight: 600;
297
+ text-transform: uppercase;
298
+ letter-spacing: 0.05em;
299
+ color: var(--rp-text-muted);
300
+ margin-bottom: var(--rp-space-md);
301
+ }
302
+
303
+ /* File input */
304
+ .rp-file-input {
305
+ width: 100%;
306
+ padding: var(--rp-space-sm);
307
+ border: 1px dashed var(--rp-border);
308
+ border-radius: var(--rp-radius);
309
+ background: var(--rp-bg);
310
+ cursor: pointer;
311
+ }
312
+
313
+ .rp-file-input:hover {
314
+ border-color: var(--rp-primary);
315
+ background: var(--rp-primary-light);
316
+ }
317
+
318
+ /* Checkbox label variant */
319
+ .rp-checkbox-label {
320
+ display: flex;
321
+ align-items: center;
322
+ gap: var(--rp-space-sm);
323
+ font-size: var(--rp-text-sm);
324
+ color: var(--rp-text-muted);
325
+ cursor: pointer;
326
+ margin-top: var(--rp-space-sm);
327
+ }
328
+
329
+ .rp-checkbox-label input[type="checkbox"] {
330
+ width: 16px;
331
+ height: 16px;
332
+ cursor: pointer;
333
+ }
334
+
335
+ /* Form hint */
336
+ .rp-form-hint {
337
+ font-size: 0.75rem;
338
+ color: var(--rp-text-muted);
339
+ margin-top: 4px;
340
+ }
341
+
342
+ /* Gallery Preview (Edit Form) */
343
+ .rp-gallery-preview {
344
+ display: grid;
345
+ grid-template-columns: repeat(2, 1fr);
346
+ gap: var(--rp-space-sm);
347
+ margin-bottom: var(--rp-space-md);
348
+ }
349
+
350
+ .rp-gallery-item {
351
+ position: relative;
352
+ background: var(--rp-bg-elevated);
353
+ border: 1px solid var(--rp-border);
354
+ border-radius: var(--rp-radius);
355
+ padding: var(--rp-space-xs);
356
+ display: flex;
357
+ flex-direction: column;
358
+ align-items: center;
359
+ gap: var(--rp-space-xs);
360
+ }
361
+
362
+ .rp-gallery-thumb {
363
+ width: 100%;
364
+ height: auto;
365
+ border-radius: calc(var(--rp-radius) - 2px);
366
+ object-fit: cover;
367
+ aspect-ratio: 1;
368
+ }
369
+
370
+ .rp-gallery-file {
371
+ display: flex;
372
+ flex-direction: column;
373
+ align-items: center;
374
+ padding: var(--rp-space-sm);
375
+ text-align: center;
376
+ }
377
+
378
+ .rp-gallery-file-icon {
379
+ font-size: 1.5rem;
380
+ margin-bottom: var(--rp-space-xs);
381
+ }
382
+
383
+ .rp-gallery-file-name {
384
+ font-size: 0.6875rem;
385
+ color: var(--rp-text-muted);
386
+ word-break: break-all;
387
+ }
388
+
389
+ .rp-gallery-remove {
390
+ font-size: 0.6875rem;
391
+ color: var(--rp-danger);
392
+ display: flex;
393
+ align-items: center;
394
+ gap: 4px;
395
+ cursor: pointer;
396
+ }
397
+
398
+ .rp-gallery-remove input[type="checkbox"] {
399
+ width: 14px;
400
+ height: 14px;
401
+ }
402
+
403
+ /* Single Attachment Preview */
404
+ .rp-attachment-preview {
405
+ margin-bottom: var(--rp-space-md);
406
+ text-align: center;
407
+ }
408
+
409
+ .rp-attachment-thumb {
410
+ max-width: 100%;
411
+ height: auto;
412
+ border-radius: var(--rp-radius);
413
+ border: 1px solid var(--rp-border);
414
+ }
415
+
416
+ .rp-attachment-remove {
417
+ font-size: 0.75rem;
418
+ color: var(--rp-danger);
419
+ display: flex;
420
+ align-items: center;
421
+ justify-content: center;
422
+ gap: 4px;
423
+ margin-top: var(--rp-space-sm);
424
+ cursor: pointer;
425
+ }
426
+
427
+ /* Gallery Grid (Show Page) */
428
+ .rp-gallery-grid {
429
+ display: grid;
430
+ grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
431
+ gap: var(--rp-space-md);
432
+ }
433
+
434
+ .rp-gallery-grid-item {
435
+ border-radius: var(--rp-radius);
436
+ overflow: hidden;
437
+ }
438
+
439
+ .rp-gallery-grid-image {
440
+ width: 100%;
441
+ height: auto;
442
+ display: block;
443
+ transition: transform 0.2s;
444
+ }
445
+
446
+ .rp-gallery-grid-item:hover .rp-gallery-grid-image {
447
+ transform: scale(1.02);
448
+ }
449
+
450
+ /* Attachment Display (Show Page) */
451
+ .rp-attachment-display {
452
+ max-width: 400px;
453
+ }
454
+
455
+ .rp-attachment-image {
456
+ width: 100%;
457
+ height: auto;
458
+ border-radius: var(--rp-radius);
459
+ }
@@ -0,0 +1,256 @@
1
+ /*
2
+ * RailsPress Admin - Layout
3
+ * Main layout, sidebar, and navigation
4
+ */
5
+
6
+ .rp-admin-layout {
7
+ display: flex;
8
+ min-height: 100vh;
9
+ }
10
+
11
+ /* Sidebar */
12
+ .rp-sidebar {
13
+ position: fixed;
14
+ top: 0;
15
+ left: 0;
16
+ width: var(--rp-sidebar-width);
17
+ height: 100vh;
18
+ background: var(--rp-sidebar-bg);
19
+ z-index: 100;
20
+ transition: width 0.25s ease;
21
+ overflow-y: auto;
22
+ overflow-x: hidden;
23
+ display: flex;
24
+ flex-direction: column;
25
+ }
26
+
27
+ .rp-sidebar-content {
28
+ padding: var(--rp-space-lg) var(--rp-space-md);
29
+ }
30
+
31
+ .rp-sidebar-header {
32
+ display: flex;
33
+ align-items: center;
34
+ justify-content: space-between;
35
+ margin-bottom: var(--rp-space-2xl);
36
+ }
37
+
38
+ .rp-logo {
39
+ font-family: var(--rp-font-display);
40
+ font-size: 1.375rem;
41
+ font-weight: 700;
42
+ color: var(--rp-sidebar-text-active);
43
+ letter-spacing: -0.01em;
44
+ margin-bottom: 0;
45
+ }
46
+
47
+ /* Sidebar Toggle Button */
48
+ .rp-sidebar-toggle {
49
+ display: flex;
50
+ align-items: center;
51
+ justify-content: center;
52
+ width: 32px;
53
+ height: 32px;
54
+ padding: 0;
55
+ background: transparent;
56
+ border: none;
57
+ border-radius: var(--rp-radius);
58
+ color: var(--rp-sidebar-text-active);
59
+ opacity: 0.7;
60
+ cursor: pointer;
61
+ transition: all 0.15s ease;
62
+ flex-shrink: 0;
63
+ }
64
+
65
+ .rp-sidebar-toggle:hover {
66
+ background: var(--rp-sidebar-hover);
67
+ opacity: 1;
68
+ }
69
+
70
+ .rp-sidebar-toggle-icon {
71
+ width: 20px;
72
+ height: 20px;
73
+ }
74
+
75
+ .rp-sidebar-toggle-icon--expand {
76
+ display: none;
77
+ }
78
+
79
+ /* Navigation */
80
+ .rp-nav {
81
+ display: flex;
82
+ flex-direction: column;
83
+ gap: 2px;
84
+ }
85
+
86
+ .rp-nav-link {
87
+ display: flex;
88
+ align-items: center;
89
+ gap: var(--rp-space-md);
90
+ padding: 10px 12px;
91
+ color: var(--rp-sidebar-text);
92
+ text-decoration: none;
93
+ font-size: 0.9375rem;
94
+ font-weight: 500;
95
+ border-radius: var(--rp-radius);
96
+ transition: all 0.15s ease;
97
+ }
98
+
99
+ .rp-nav-link:hover {
100
+ background: var(--rp-sidebar-hover);
101
+ color: var(--rp-sidebar-text-active);
102
+ }
103
+
104
+ .rp-nav-link--active {
105
+ background: var(--rp-sidebar-hover);
106
+ color: var(--rp-sidebar-text-active);
107
+ }
108
+
109
+ .rp-nav-icon {
110
+ width: 18px;
111
+ height: 18px;
112
+ opacity: 0.7;
113
+ flex-shrink: 0;
114
+ }
115
+
116
+ .rp-nav-link:hover .rp-nav-icon,
117
+ .rp-nav-link--active .rp-nav-icon {
118
+ opacity: 1;
119
+ }
120
+
121
+ .rp-nav-text {
122
+ white-space: nowrap;
123
+ overflow: hidden;
124
+ transition: opacity 0.2s ease;
125
+ }
126
+
127
+ .rp-nav-divider {
128
+ height: 1px;
129
+ background: var(--rp-sidebar-hover);
130
+ margin: var(--rp-space-md) 0;
131
+ }
132
+
133
+ /* Main Content Area */
134
+ .rp-main {
135
+ flex: 1;
136
+ margin-left: var(--rp-sidebar-width);
137
+ padding: var(--rp-space-xl) var(--rp-space-2xl);
138
+ min-width: 0;
139
+ transition: margin-left 0.25s ease;
140
+ }
141
+
142
+ /* Collapsed Sidebar State */
143
+ .rp-sidebar--collapsed {
144
+ width: var(--rp-sidebar-width-collapsed);
145
+ }
146
+
147
+ .rp-sidebar--collapsed .rp-sidebar-content {
148
+ padding: var(--rp-space-lg) var(--rp-space-sm);
149
+ }
150
+
151
+ .rp-sidebar--collapsed .rp-sidebar-header {
152
+ justify-content: center;
153
+ }
154
+
155
+ .rp-sidebar--collapsed .rp-logo {
156
+ display: none;
157
+ }
158
+
159
+ .rp-sidebar--collapsed .rp-sidebar-toggle {
160
+ width: 36px;
161
+ height: 36px;
162
+ }
163
+
164
+ .rp-sidebar--collapsed .rp-sidebar-toggle-icon {
165
+ width: 20px;
166
+ height: 20px;
167
+ }
168
+
169
+ .rp-sidebar--collapsed .rp-nav-link {
170
+ justify-content: center;
171
+ padding: 10px;
172
+ }
173
+
174
+ .rp-sidebar--collapsed .rp-nav-text {
175
+ position: absolute;
176
+ width: 1px;
177
+ height: 1px;
178
+ padding: 0;
179
+ margin: -1px;
180
+ overflow: hidden;
181
+ clip: rect(0, 0, 0, 0);
182
+ border: 0;
183
+ }
184
+
185
+ .rp-sidebar--collapsed .rp-nav-icon {
186
+ width: 22px;
187
+ height: 22px;
188
+ }
189
+
190
+ .rp-sidebar--collapsed .rp-sidebar-toggle-icon--collapse {
191
+ display: none;
192
+ }
193
+
194
+ .rp-sidebar--collapsed .rp-sidebar-toggle-icon--expand {
195
+ display: block;
196
+ }
197
+
198
+ /* Main content adjustment when sidebar collapsed */
199
+ .rp-admin-layout--sidebar-collapsed .rp-main {
200
+ margin-left: var(--rp-sidebar-width-collapsed);
201
+ }
202
+
203
+ /* Mobile Header */
204
+ .rp-mobile-header {
205
+ display: none;
206
+ position: fixed;
207
+ top: 0;
208
+ left: 0;
209
+ right: 0;
210
+ height: var(--rp-header-height);
211
+ background: var(--rp-sidebar-bg);
212
+ z-index: 90;
213
+ padding: 0 var(--rp-space-md);
214
+ align-items: center;
215
+ justify-content: space-between;
216
+ }
217
+
218
+ .rp-hamburger {
219
+ display: flex;
220
+ flex-direction: column;
221
+ justify-content: center;
222
+ gap: 5px;
223
+ width: 44px;
224
+ height: 44px;
225
+ background: transparent;
226
+ border: none;
227
+ cursor: pointer;
228
+ padding: 10px;
229
+ }
230
+
231
+ .rp-hamburger span {
232
+ display: block;
233
+ width: 22px;
234
+ height: 2px;
235
+ background: var(--rp-sidebar-text-active);
236
+ border-radius: 1px;
237
+ }
238
+
239
+ .rp-mobile-logo {
240
+ font-family: var(--rp-font-display);
241
+ font-size: 1.125rem;
242
+ font-weight: 700;
243
+ color: var(--rp-sidebar-text-active);
244
+ }
245
+
246
+ .rp-overlay {
247
+ display: none;
248
+ position: fixed;
249
+ inset: 0;
250
+ background: rgba(26, 29, 33, 0.5);
251
+ z-index: 95;
252
+ }
253
+
254
+ .rp-overlay--visible {
255
+ display: block;
256
+ }
@@ -0,0 +1,24 @@
1
+ /*
2
+ * RailsPress Admin - Lists
3
+ * List components
4
+ */
5
+
6
+ .rp-list {
7
+ list-style: none;
8
+ }
9
+
10
+ .rp-list-item {
11
+ display: flex;
12
+ align-items: center;
13
+ justify-content: space-between;
14
+ padding: var(--rp-space-md);
15
+ border-bottom: 1px solid var(--rp-border-light);
16
+ }
17
+
18
+ .rp-list-item:hover {
19
+ background: var(--rp-bg);
20
+ }
21
+
22
+ .rp-list-item:last-child {
23
+ border-bottom: none;
24
+ }