rails_admin_next 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 (184) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +46 -0
  3. data/LICENSE.md +21 -0
  4. data/README.md +317 -0
  5. data/Rakefile +25 -0
  6. data/app/assets/javascripts/rails_admin/custom/ui.js +1 -0
  7. data/app/assets/stylesheets/rails_admin/framework.css +2375 -0
  8. data/app/assets/stylesheets/rails_admin/skin.css +472 -0
  9. data/app/assets/stylesheets/rails_admin/tokens.css +281 -0
  10. data/app/assets/stylesheets/rails_admin.css +47 -0
  11. data/app/controllers/rails_admin_next/application_controller.rb +98 -0
  12. data/app/controllers/rails_admin_next/main_controller.rb +185 -0
  13. data/app/helpers/rails_admin_next/application_helper.rb +254 -0
  14. data/app/helpers/rails_admin_next/form_builder.rb +173 -0
  15. data/app/helpers/rails_admin_next/main_helper.rb +63 -0
  16. data/app/views/layouts/rails_admin_next/_head.html.erb +29 -0
  17. data/app/views/layouts/rails_admin_next/_navigation.html.erb +18 -0
  18. data/app/views/layouts/rails_admin_next/_secondary_navigation.html.erb +27 -0
  19. data/app/views/layouts/rails_admin_next/_sidebar_navigation.html.erb +6 -0
  20. data/app/views/layouts/rails_admin_next/application.html.erb +42 -0
  21. data/app/views/layouts/rails_admin_next/content.html.erb +22 -0
  22. data/app/views/layouts/rails_admin_next/modal.js.erb +7 -0
  23. data/app/views/rails_admin_next/main/_dashboard_history.html.erb +46 -0
  24. data/app/views/rails_admin_next/main/_delete_notice.html.erb +36 -0
  25. data/app/views/rails_admin_next/main/_form_action_text.html.erb +2 -0
  26. data/app/views/rails_admin_next/main/_form_boolean.html.erb +15 -0
  27. data/app/views/rails_admin_next/main/_form_colorpicker.html.erb +6 -0
  28. data/app/views/rails_admin_next/main/_form_datetime.html.erb +14 -0
  29. data/app/views/rails_admin_next/main/_form_enumeration.html.erb +26 -0
  30. data/app/views/rails_admin_next/main/_form_field.html.erb +2 -0
  31. data/app/views/rails_admin_next/main/_form_file_upload.html.erb +18 -0
  32. data/app/views/rails_admin_next/main/_form_filtering_multiselect.html.erb +20 -0
  33. data/app/views/rails_admin_next/main/_form_filtering_select.html.erb +22 -0
  34. data/app/views/rails_admin_next/main/_form_multiple_file_upload.html.erb +21 -0
  35. data/app/views/rails_admin_next/main/_form_nested_many.html.erb +20 -0
  36. data/app/views/rails_admin_next/main/_form_nested_one.html.erb +19 -0
  37. data/app/views/rails_admin_next/main/_form_polymorphic_association.html.erb +24 -0
  38. data/app/views/rails_admin_next/main/_form_text.html.erb +2 -0
  39. data/app/views/rails_admin_next/main/_pagination.html.erb +54 -0
  40. data/app/views/rails_admin_next/main/_submit_buttons.html.erb +26 -0
  41. data/app/views/rails_admin_next/main/bulk_delete.html.erb +19 -0
  42. data/app/views/rails_admin_next/main/dashboard.html.erb +64 -0
  43. data/app/views/rails_admin_next/main/delete.html.erb +21 -0
  44. data/app/views/rails_admin_next/main/edit.html.erb +3 -0
  45. data/app/views/rails_admin_next/main/export.html.erb +149 -0
  46. data/app/views/rails_admin_next/main/history.html.erb +80 -0
  47. data/app/views/rails_admin_next/main/index.html.erb +186 -0
  48. data/app/views/rails_admin_next/main/new.html.erb +3 -0
  49. data/app/views/rails_admin_next/main/show.html.erb +30 -0
  50. data/config/brakeman.ignore +145 -0
  51. data/config/importmap.rails_admin.rb +29 -0
  52. data/config/initializers/active_record_extensions.rb +21 -0
  53. data/config/locales/rails_admin_next.en.yml +158 -0
  54. data/config/routes.rb +14 -0
  55. data/lib/generators/rails_admin_next/install_generator.rb +39 -0
  56. data/lib/generators/rails_admin_next/templates/initializer.erb +40 -0
  57. data/lib/generators/rails_admin_next/utils.rb +21 -0
  58. data/lib/rails_admin_next/abstract_model.rb +266 -0
  59. data/lib/rails_admin_next/adapters/active_record/association.rb +130 -0
  60. data/lib/rails_admin_next/adapters/active_record/object_extension.rb +13 -0
  61. data/lib/rails_admin_next/adapters/active_record/property.rb +58 -0
  62. data/lib/rails_admin_next/adapters/active_record.rb +371 -0
  63. data/lib/rails_admin_next/config/actions/base.rb +160 -0
  64. data/lib/rails_admin_next/config/actions/bulk_delete.rb +67 -0
  65. data/lib/rails_admin_next/config/actions/dashboard.rb +62 -0
  66. data/lib/rails_admin_next/config/actions/delete.rb +58 -0
  67. data/lib/rails_admin_next/config/actions/edit.rb +56 -0
  68. data/lib/rails_admin_next/config/actions/export.rb +47 -0
  69. data/lib/rails_admin_next/config/actions/history_index.rb +40 -0
  70. data/lib/rails_admin_next/config/actions/history_show.rb +40 -0
  71. data/lib/rails_admin_next/config/actions/index.rb +108 -0
  72. data/lib/rails_admin_next/config/actions/new.rb +69 -0
  73. data/lib/rails_admin_next/config/actions/show.rb +36 -0
  74. data/lib/rails_admin_next/config/actions/show_in_app.rb +37 -0
  75. data/lib/rails_admin_next/config/actions.rb +122 -0
  76. data/lib/rails_admin_next/config/configurable.rb +107 -0
  77. data/lib/rails_admin_next/config/const_load_suppressor.rb +78 -0
  78. data/lib/rails_admin_next/config/fields/association.rb +169 -0
  79. data/lib/rails_admin_next/config/fields/base.rb +391 -0
  80. data/lib/rails_admin_next/config/fields/collection_association.rb +90 -0
  81. data/lib/rails_admin_next/config/fields/factories/action_text.rb +14 -0
  82. data/lib/rails_admin_next/config/fields/factories/active_storage.rb +34 -0
  83. data/lib/rails_admin_next/config/fields/factories/association.rb +32 -0
  84. data/lib/rails_admin_next/config/fields/factories/encrypted_password.rb +28 -0
  85. data/lib/rails_admin_next/config/fields/factories/enum.rb +23 -0
  86. data/lib/rails_admin_next/config/fields/factories/password.rb +19 -0
  87. data/lib/rails_admin_next/config/fields/group.rb +77 -0
  88. data/lib/rails_admin_next/config/fields/singular_association.rb +62 -0
  89. data/lib/rails_admin_next/config/fields/types/action_text.rb +20 -0
  90. data/lib/rails_admin_next/config/fields/types/active_record_enum.rb +62 -0
  91. data/lib/rails_admin_next/config/fields/types/active_storage.rb +70 -0
  92. data/lib/rails_admin_next/config/fields/types/all.rb +32 -0
  93. data/lib/rails_admin_next/config/fields/types/belongs_to_association.rb +48 -0
  94. data/lib/rails_admin_next/config/fields/types/boolean.rb +70 -0
  95. data/lib/rails_admin_next/config/fields/types/citext.rb +15 -0
  96. data/lib/rails_admin_next/config/fields/types/color.rb +43 -0
  97. data/lib/rails_admin_next/config/fields/types/date.rb +38 -0
  98. data/lib/rails_admin_next/config/fields/types/datetime.rb +79 -0
  99. data/lib/rails_admin_next/config/fields/types/decimal.rb +23 -0
  100. data/lib/rails_admin_next/config/fields/types/enum.rb +52 -0
  101. data/lib/rails_admin_next/config/fields/types/file_upload.rb +87 -0
  102. data/lib/rails_admin_next/config/fields/types/float.rb +23 -0
  103. data/lib/rails_admin_next/config/fields/types/has_and_belongs_to_many_association.rb +16 -0
  104. data/lib/rails_admin_next/config/fields/types/has_many_association.rb +16 -0
  105. data/lib/rails_admin_next/config/fields/types/has_one_association.rb +35 -0
  106. data/lib/rails_admin_next/config/fields/types/hidden.rb +31 -0
  107. data/lib/rails_admin_next/config/fields/types/inet.rb +15 -0
  108. data/lib/rails_admin_next/config/fields/types/integer.rb +20 -0
  109. data/lib/rails_admin_next/config/fields/types/json.rb +37 -0
  110. data/lib/rails_admin_next/config/fields/types/multiple_active_storage.rb +82 -0
  111. data/lib/rails_admin_next/config/fields/types/multiple_file_upload.rb +134 -0
  112. data/lib/rails_admin_next/config/fields/types/numeric.rb +24 -0
  113. data/lib/rails_admin_next/config/fields/types/password.rb +45 -0
  114. data/lib/rails_admin_next/config/fields/types/polymorphic_association.rb +118 -0
  115. data/lib/rails_admin_next/config/fields/types/serialized.rb +28 -0
  116. data/lib/rails_admin_next/config/fields/types/string.rb +50 -0
  117. data/lib/rails_admin_next/config/fields/types/string_like.rb +25 -0
  118. data/lib/rails_admin_next/config/fields/types/text.rb +28 -0
  119. data/lib/rails_admin_next/config/fields/types/time.rb +39 -0
  120. data/lib/rails_admin_next/config/fields/types/timestamp.rb +16 -0
  121. data/lib/rails_admin_next/config/fields/types/uuid.rb +15 -0
  122. data/lib/rails_admin_next/config/fields/types.rb +29 -0
  123. data/lib/rails_admin_next/config/fields.rb +88 -0
  124. data/lib/rails_admin_next/config/groupable.rb +20 -0
  125. data/lib/rails_admin_next/config/has_description.rb +14 -0
  126. data/lib/rails_admin_next/config/has_fields.rb +144 -0
  127. data/lib/rails_admin_next/config/has_groups.rb +27 -0
  128. data/lib/rails_admin_next/config/hideable.rb +30 -0
  129. data/lib/rails_admin_next/config/inspectable.rb +39 -0
  130. data/lib/rails_admin_next/config/lazy_model.rb +74 -0
  131. data/lib/rails_admin_next/config/model.rb +126 -0
  132. data/lib/rails_admin_next/config/proxyable/proxy.rb +42 -0
  133. data/lib/rails_admin_next/config/proxyable.rb +26 -0
  134. data/lib/rails_admin_next/config/sections/base.rb +36 -0
  135. data/lib/rails_admin_next/config/sections/create.rb +13 -0
  136. data/lib/rails_admin_next/config/sections/edit.rb +13 -0
  137. data/lib/rails_admin_next/config/sections/export.rb +13 -0
  138. data/lib/rails_admin_next/config/sections/list.rb +63 -0
  139. data/lib/rails_admin_next/config/sections/modal.rb +12 -0
  140. data/lib/rails_admin_next/config/sections/nested.rb +12 -0
  141. data/lib/rails_admin_next/config/sections/show.rb +12 -0
  142. data/lib/rails_admin_next/config/sections/update.rb +12 -0
  143. data/lib/rails_admin_next/config/sections.rb +39 -0
  144. data/lib/rails_admin_next/config.rb +436 -0
  145. data/lib/rails_admin_next/engine.rb +91 -0
  146. data/lib/rails_admin_next/extension.rb +35 -0
  147. data/lib/rails_admin_next/extensions/cancancan/authorization_adapter.rb +90 -0
  148. data/lib/rails_admin_next/extensions/cancancan.rb +5 -0
  149. data/lib/rails_admin_next/extensions/controller_extension.rb +8 -0
  150. data/lib/rails_admin_next/extensions/paper_trail/auditing_adapter.rb +192 -0
  151. data/lib/rails_admin_next/extensions/paper_trail.rb +5 -0
  152. data/lib/rails_admin_next/extensions/pundit/authorization_adapter.rb +72 -0
  153. data/lib/rails_admin_next/extensions/pundit.rb +5 -0
  154. data/lib/rails_admin_next/extensions/url_for_extension.rb +15 -0
  155. data/lib/rails_admin_next/icons.rb +143 -0
  156. data/lib/rails_admin_next/support/composite_keys_serializer.rb +15 -0
  157. data/lib/rails_admin_next/support/csv_converter.rb +100 -0
  158. data/lib/rails_admin_next/support/hash_helper.rb +31 -0
  159. data/lib/rails_admin_next/support/paginated_collection.rb +79 -0
  160. data/lib/rails_admin_next/version.rb +17 -0
  161. data/lib/rails_admin_next.rb +72 -0
  162. data/lib/tasks/rails_admin.rake +40 -0
  163. data/src/rails_admin/application.js +15 -0
  164. data/src/rails_admin/base.js +12 -0
  165. data/src/rails_admin/controllers/alert_controller.js +28 -0
  166. data/src/rails_admin/controllers/collapse_controller.js +16 -0
  167. data/src/rails_admin/controllers/dropdown_controller.js +110 -0
  168. data/src/rails_admin/controllers/feedback_controller.js +73 -0
  169. data/src/rails_admin/controllers/filter_box_controller.js +346 -0
  170. data/src/rails_admin/controllers/filtering_multiselect_controller.js +386 -0
  171. data/src/rails_admin/controllers/filtering_select_controller.js +509 -0
  172. data/src/rails_admin/controllers/index.js +31 -0
  173. data/src/rails_admin/controllers/modal_controller.js +142 -0
  174. data/src/rails_admin/controllers/nested_form_controller.js +117 -0
  175. data/src/rails_admin/controllers/polymorphic_controller.js +26 -0
  176. data/src/rails_admin/controllers/remote_form_controller.js +173 -0
  177. data/src/rails_admin/controllers/sidescroll_controller.js +23 -0
  178. data/src/rails_admin/dom-ready.js +20 -0
  179. data/src/rails_admin/dom.js +19 -0
  180. data/src/rails_admin/i18n.js +20 -0
  181. data/src/rails_admin/icons.js +64 -0
  182. data/src/rails_admin/interactions.js +221 -0
  183. data/src/rails_admin/select_query.js +65 -0
  184. metadata +346 -0
@@ -0,0 +1,472 @@
1
+ /*
2
+ * rails_admin_next — the engine's own widgets, inline-SVG icons, and admin skin.
3
+ * Loaded by rails_admin.css into the ra.skin cascade layer; see that file's header for the
4
+ * browser floor and the styled-vocabulary contract.
5
+ *
6
+ * Written with native CSS nesting, always under single-selector parents: `&` resolves via
7
+ * :is(), whose specificity for a single-item list equals the flat form, so every selector
8
+ * here matches with exactly the specificity of its pre-nesting equivalent.
9
+ */
10
+
11
+ /* === Multiselect widget ================================================= */
12
+ .ra-multiselect {
13
+ .ra-multiselect-header {
14
+ margin-bottom: 5px;
15
+ clear: right;
16
+ }
17
+ .ra-multiselect-search {
18
+ width: 180px;
19
+ }
20
+ .ra-multiselect-column {
21
+ float: left;
22
+ .wrapper {
23
+ overflow-x: auto;
24
+ select {
25
+ height: auto;
26
+ min-height: 120px;
27
+ margin-bottom: 5px;
28
+ min-width: 200px;
29
+ }
30
+ }
31
+ }
32
+ .ra-multiselect-center {
33
+ width: 30px;
34
+ padding-top: 15px;
35
+ text-align: center;
36
+ a {
37
+ display: block;
38
+ margin: 5px auto;
39
+ }
40
+ }
41
+ .ra-multiselect-item-add,
42
+ .ra-multiselect-item-remove,
43
+ .ra-multiselect-item-up,
44
+ .ra-multiselect-item-down,
45
+ .ra-multiselect-item-add-all,
46
+ .ra-multiselect-item-remove-all {
47
+ color: var(--ra-gray-400);
48
+ font-size: 16px;
49
+ margin-right: 4px;
50
+ text-decoration: none;
51
+ &:hover {
52
+ color: var(--ra-gray-700);
53
+ }
54
+ }
55
+ }
56
+
57
+ /* === Form widget extras ================================================= */
58
+ .controls img.preview {
59
+ max-height: 200px;
60
+ max-width: 300px;
61
+ }
62
+ .form-group.hidden_type {
63
+ display: none;
64
+ }
65
+ .links .list-inline .disabled span {
66
+ color: var(--ra-gray-600);
67
+ }
68
+ /* Submit rows lay out with flex + gap so a wrapped row (narrow viewport,
69
+ many buttons) breathes instead of touching. The .extra_buttons grouping
70
+ span joins the same flex row via display: contents. */
71
+ .form-actions {
72
+ &,
73
+ > [class*="col-"] {
74
+ align-items: center;
75
+ display: flex;
76
+ flex-wrap: wrap;
77
+ gap: 0.5rem;
78
+ }
79
+
80
+ .extra_buttons {
81
+ display: contents;
82
+ }
83
+ }
84
+
85
+ /* === Inline-SVG icons =================================================== */
86
+ /* Inline-SVG icons (RailsAdminNext::ApplicationHelper#rails_admin_icon). Sized
87
+ like a text glyph and tinted by currentColor so icons flow inline with text.
88
+ Width is left to auto so each glyph keeps its own viewBox aspect ratio. */
89
+ .rails-admin-icon {
90
+ display: inline-block;
91
+ height: 1em;
92
+ width: auto;
93
+ overflow: visible;
94
+ vertical-align: -0.125em;
95
+ fill: currentColor;
96
+ /* Collapsed form-legend chevron: rotate a single chevron-down 90° to point
97
+ right instead of swapping in a second glyph for the collapsed state. The
98
+ sidebar's <details> groups rotate theirs via details:not([open]) instead. */
99
+ &.collapsed {
100
+ transform: rotate(-90deg);
101
+ }
102
+ }
103
+
104
+ /* === Admin skin: layout and navbar ====================================== */
105
+ body.rails_admin {
106
+ padding-top: 3.275rem;
107
+ .navbar .edit_user_root_link {
108
+ position: relative;
109
+ img {
110
+ position: absolute;
111
+ top: calc((40px - 30px) / 2);
112
+ + span {
113
+ margin-left: 35px;
114
+ }
115
+ }
116
+ }
117
+ }
118
+
119
+ /* === Admin skin: sidebar navigation ===================================== */
120
+ /* Each group is a native <details>/<summary> disclosure; the chevron icon is
121
+ the marker, so the browser's default one is suppressed. */
122
+ body.rails_admin .sidebar.btn-toggle-nav {
123
+ padding: 0;
124
+ summary.btn-toggle {
125
+ margin-top: calc(1.5rem / 2);
126
+ padding: 3px calc(1.5rem / 2);
127
+ font-weight: bold;
128
+ color: var(--ra-gray-600);
129
+ cursor: pointer;
130
+ list-style: none;
131
+ &::marker,
132
+ &::-webkit-details-marker {
133
+ display: none;
134
+ }
135
+ }
136
+ details[open] > summary.btn-toggle {
137
+ color: var(--ra-gray-700);
138
+ }
139
+ /* Collapsed group: rotate the chevron-down 90° to point right, matching the
140
+ .rails-admin-icon.collapsed rotation the form legends still use. */
141
+ details:not([open]) .rails-admin-icon {
142
+ transform: rotate(-90deg);
143
+ }
144
+ .btn-toggle-nav > li > a {
145
+ padding: calc(0.5rem / 2) calc(1.5rem / 2);
146
+ /* Label is white in light, black in dark — AA on the
147
+ lightened dark --ra-primary fill, matching the button/badge pairing. */
148
+ &.active {
149
+ background-color: var(--ra-primary);
150
+ color: var(--ra-tint-target);
151
+ }
152
+ &:hover {
153
+ background-color: var(--ra-primary);
154
+ color: var(--ra-tint-target);
155
+ }
156
+ &.nav-level-1 {
157
+ padding-left: 1.5rem;
158
+ }
159
+ &.nav-level-2 {
160
+ padding-left: 2.25rem;
161
+ }
162
+ &.nav-level-3 {
163
+ padding-left: 3rem;
164
+ }
165
+ }
166
+ }
167
+
168
+ /* === Admin skin: edit form and nested-field tabs ======================== */
169
+ body.rails_admin form.main {
170
+ .control-group .hidden_type {
171
+ display: none;
172
+ }
173
+ .tab-content {
174
+ .tab-pane {
175
+ border-left: 5px solid var(--ra-primary);
176
+ position: relative;
177
+ fieldset {
178
+ padding-top: 30px;
179
+ }
180
+ .form-group {
181
+ margin-right: 0;
182
+ margin-left: -5px;
183
+ }
184
+ > .remove_nested_fields {
185
+ display: block;
186
+ opacity: 0;
187
+ position: absolute;
188
+ top: 0px;
189
+ left: 5px;
190
+ transition: opacity 0.15s ease;
191
+ @media (prefers-reduced-motion: reduce) {
192
+ transition: none;
193
+ }
194
+ }
195
+ &:hover > .remove_nested_fields {
196
+ opacity: 1;
197
+ }
198
+ &.marked_for_destruction {
199
+ opacity: 0.4;
200
+ > .remove_nested_fields {
201
+ opacity: 1;
202
+ }
203
+ }
204
+ }
205
+ /* Nested sub-forms: each nesting level re-tints the pane's accent bar and
206
+ walks the pane and its controls rightward. Deeper selectors carry higher
207
+ specificity, so each level overrides the one above it. */
208
+ .tab-content {
209
+ .tab-pane {
210
+ border-color: var(--ra-nested-form-accent-1);
211
+ margin-left: 10px;
212
+ .form-group {
213
+ margin-left: -15px;
214
+ }
215
+ }
216
+ .tab-content {
217
+ .tab-pane {
218
+ border-color: var(--ra-nested-form-accent-2);
219
+ margin-left: 20px;
220
+ .form-group {
221
+ margin-left: -25px;
222
+ }
223
+ }
224
+ .tab-content .tab-pane {
225
+ border-color: var(--ra-nested-form-accent-3);
226
+ margin-left: 30px;
227
+ .form-group {
228
+ margin-left: -35px;
229
+ }
230
+ }
231
+ }
232
+ }
233
+ }
234
+ }
235
+ /* Singular (has_one / belongs_to) associations hold at most one subform, so the
236
+ add control hides while a subform occupies the container — INCLUDING one
237
+ marked for destruction: singular fields_for renders unindexed names, so a
238
+ marked subform plus a fresh replacement would post colliding attributes and
239
+ silently update the record instead of destroy+create. Removing the subform
240
+ outright (new records) reshows the control. Child combinators keep a nested
241
+ inner association's subforms from occupying the outer slot. */
242
+ body.rails_admin
243
+ [data-controller~="nested-form"][data-nested-form-singular-value="true"]:has(
244
+ > [data-nested-form-target="container"]
245
+ > [data-nested-form-target="subform"]
246
+ )
247
+ > .add_nested_fields {
248
+ display: none;
249
+ }
250
+ body.rails_admin .nav.nav-tabs {
251
+ li.nav-item.icon + li.nav-item.dropdown {
252
+ margin-left: auto;
253
+ }
254
+ .dropdown-menu {
255
+ margin: 0;
256
+ }
257
+ }
258
+
259
+ /* === Admin skin: list table ============================================= */
260
+ body.rails_admin .table {
261
+ height: 100%;
262
+ /* Numerals align down columns (ids, counts, dates). */
263
+ font-variant-numeric: tabular-nums;
264
+ > thead > tr > th,
265
+ > tbody > tr > th,
266
+ > tfoot > tr > th {
267
+ border-bottom: 0px;
268
+ }
269
+ .header {
270
+ cursor: pointer;
271
+ padding-right: 18px;
272
+ &:after {
273
+ content: "";
274
+ float: right;
275
+ margin-top: 7px;
276
+ margin-left: 8px;
277
+ margin-right: -16px;
278
+ border-width: 0 4px 4px;
279
+ border-style: solid;
280
+ border-color: var(--ra-body-color) transparent;
281
+ visibility: hidden;
282
+ }
283
+ &:hover:after {
284
+ visibility: visible;
285
+ }
286
+ }
287
+ .headerSortUp,
288
+ .headerSortDown {
289
+ background-color: color-mix(in srgb, var(--ra-info) 25%, transparent);
290
+ /* Surface-colored halo behind the sorted-header label; its token's dark
291
+ arm matches the dark body bg so it never reads as a glow. */
292
+ text-shadow: 0 1px 1px
293
+ color-mix(in srgb, var(--ra-header-sort-shadow) 75%, transparent);
294
+ }
295
+ .headerSortDown {
296
+ &:after,
297
+ &:hover:after {
298
+ visibility: visible;
299
+ opacity: 0.6;
300
+ }
301
+ }
302
+ .headerSortUp:after {
303
+ border-bottom: none;
304
+ border-left: 4px solid transparent;
305
+ border-right: 4px solid transparent;
306
+ border-top: 4px solid var(--ra-body-color);
307
+ visibility: visible;
308
+ opacity: 0.6;
309
+ }
310
+ th {
311
+ white-space: nowrap;
312
+ }
313
+ td {
314
+ white-space: nowrap;
315
+ overflow: hidden;
316
+ text-overflow: ellipsis;
317
+ max-width: 150px;
318
+ }
319
+ th,
320
+ td {
321
+ padding: 5px 10px;
322
+ }
323
+ .sticky {
324
+ position: sticky;
325
+ }
326
+ th.last,
327
+ td.last {
328
+ position: sticky;
329
+ right: 0px;
330
+ }
331
+ /* Bulk-selected rows: a quiet primary tint on every cell (td-level so the
332
+ position: sticky cells tint too). Painted as an extra inset box-shadow
333
+ layered over the striped/hover accent shadow it replaces — shadows paint
334
+ above background-color, so the translucent tint composes over the opaque
335
+ #sidescroll body-bg cells and any row_css_class contextual variant bg
336
+ (table-danger etc.), where a background overlay would be masked or mask. */
337
+ tr:has(input[name="bulk_ids[]"]:checked) > td {
338
+ box-shadow: inset 0 0 0 9999px
339
+ color-mix(in srgb, var(--ra-primary) 8%, transparent),
340
+ inset 0 0 0 9999px var(--ra-table-accent-bg);
341
+ }
342
+ td.links {
343
+ max-width: none;
344
+ .list-inline {
345
+ margin-bottom: 0;
346
+ li {
347
+ display: inline-block;
348
+ padding: 0 3px;
349
+ .nav-link {
350
+ padding: 0 0.1em;
351
+ }
352
+ }
353
+ }
354
+ }
355
+ .shrink {
356
+ width: 1px;
357
+ white-space: nowrap;
358
+ }
359
+ th.created_at {
360
+ width: 160px;
361
+ }
362
+ th.username {
363
+ width: 140px;
364
+ }
365
+ th.item {
366
+ width: 60px;
367
+ }
368
+ .progress {
369
+ height: 100%;
370
+ }
371
+ }
372
+
373
+ /* === Admin skin: filters, side-scroll, pagination ======================= */
374
+ /* The filter rows ARE the state: everything downstream derives from them via
375
+ :has(), with no JS mirroring. The divider follows row presence; each row's
376
+ additional value fieldsets follow its operator <select>. */
377
+
378
+ /* Divider: visible only while filter rows exist. Keyed on .filter presence,
379
+ not :empty — whitespace text nodes would defeat :empty. */
380
+ body.rails_admin #filters_box:not(:has(.filter)) + hr.filters_box {
381
+ display: none;
382
+ }
383
+
384
+ body.rails_admin #filters_box {
385
+ .form-control {
386
+ display: inline-block;
387
+ vertical-align: middle;
388
+ width: auto;
389
+ }
390
+ /* Operator-driven fieldset switching. Every rule is scoped to
391
+ select.switch-additional-fieldsets: enum and boolean rows reuse a <select>
392
+ as the VALUE control, and an unscoped option:checked[...] would
393
+ false-trigger on it. */
394
+ .filter .additional-fieldset {
395
+ display: inline-block;
396
+ }
397
+ /* default/between operand fieldsets (date, datetime, time, numeric) show
398
+ only while the matching operator option is selected; operators with no
399
+ operand (today, this_week, presence checks, "...") hide them all. A row
400
+ built from a nil server-sent operator marks the valueless disabled
401
+ separator selected (a #buildOperator quirk: getAttribute("value") and a
402
+ nil operator are both null), so the :not([value]) arm targets that same
403
+ state and shows the default operand fieldset for a nil operator. Users
404
+ can never re-select the disabled separator, so the arm is inert after
405
+ any operator change. */
406
+ .filter .additional-fieldset.between,
407
+ .filter:has(select.switch-additional-fieldsets) .additional-fieldset.default {
408
+ display: none;
409
+ }
410
+ .filter:has(
411
+ select.switch-additional-fieldsets
412
+ option:checked:is([data-additional-fieldset="default"], :not([value]))
413
+ )
414
+ .additional-fieldset.default,
415
+ .filter:has(
416
+ select.switch-additional-fieldsets
417
+ option:checked[data-additional-fieldset="between"]
418
+ )
419
+ .additional-fieldset.between {
420
+ display: inline-block;
421
+ }
422
+ /* String-like rows have a single bare value fieldset that stays visible
423
+ through the "..." discard operator (matching the server-driven initial
424
+ render); only the valueless presence operators hide it. */
425
+ .filter:has(
426
+ select.switch-additional-fieldsets
427
+ option:checked:is([value="_present"], [value="_blank"])
428
+ )
429
+ .additional-fieldset:not(.default, .between) {
430
+ display: none;
431
+ }
432
+ }
433
+ body.rails_admin #sidescroll {
434
+ margin-bottom: 20px;
435
+ overflow-x: auto;
436
+ /* Horizontal wheel/trackpad scrolls stop at the table edge instead of
437
+ chaining into a browser back/forward navigation gesture. */
438
+ overscroll-behavior: contain;
439
+ .table {
440
+ margin-bottom: 0;
441
+ }
442
+ .table-striped > tbody > tr > td,
443
+ .table-striped > thead > tr > th {
444
+ background-color: var(--ra-body-bg);
445
+ }
446
+ .table {
447
+ .sticky.headerSortUp,
448
+ .sticky.headerSortDown,
449
+ .last.headerSortUp,
450
+ .last.headerSortDown {
451
+ background-color: var(--ra-sticky-sort-bg);
452
+ }
453
+ }
454
+ }
455
+ body.rails_admin .pagination .page-item {
456
+ white-space: nowrap;
457
+ }
458
+
459
+ /* === Admin skin: responsive adjustments ================================= */
460
+ @media screen and (min-width: 576px) {
461
+ body.rails_admin .sidebar.btn-toggle-nav {
462
+ position: fixed;
463
+ top: 3.275rem;
464
+ bottom: 0;
465
+ overflow-y: auto;
466
+ /* Sidebar scrolling stops at its own ends instead of chaining to the
467
+ page, and (with classic scrollbars) the nav keeps its width whether or
468
+ not the vertical scrollbar is showing. */
469
+ overscroll-behavior: contain;
470
+ scrollbar-gutter: stable;
471
+ }
472
+ }