mensa 0.8.0 → 0.8.2

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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/.shipkit.yml +1 -1
  3. data/Gemfile.lock +2 -2
  4. data/app/assets/tailwind/mensa/engine.css +6 -0
  5. data/app/components/mensa/add_filter/component.css +68 -70
  6. data/app/components/mensa/add_filter/component.html.erb +1 -1
  7. data/app/components/mensa/column_customizer/component.css +33 -32
  8. data/app/components/mensa/column_customizer/component_controller.js +1 -1
  9. data/app/components/mensa/control_bar/component.css +121 -125
  10. data/app/components/mensa/empty_state/component.css +13 -13
  11. data/app/components/mensa/filter_pill/component.css +26 -26
  12. data/app/components/mensa/filter_pill_list/component.css +35 -37
  13. data/app/components/mensa/filter_pill_list/component_controller.js +13 -6
  14. data/app/components/mensa/group_by/component.css +28 -32
  15. data/app/components/mensa/group_by/component_controller.js +3 -3
  16. data/app/components/mensa/group_header/component.css +21 -23
  17. data/app/components/mensa/group_header/component_controller.js +7 -2
  18. data/app/components/mensa/search/component.css +53 -55
  19. data/app/components/mensa/table/component.css +7 -7
  20. data/app/components/mensa/table/component.html.erb +1 -0
  21. data/app/components/mensa/table/component_controller.js +3 -2
  22. data/app/components/mensa/view/component.css +10 -10
  23. data/app/components/mensa/view/component.html.erb +1 -1
  24. data/app/components/mensa/view/paging.css +2 -2
  25. data/app/components/mensa/views/component.css +103 -105
  26. data/app/javascript/mensa/controllers/application_controller.js +6 -0
  27. data/app/tables/mensa/base.rb +16 -2
  28. data/lib/generators/mensa/tailwind_config_generator.rb +4 -0
  29. data/lib/mensa/version.rb +1 -1
  30. data/lib/tasks/mensa_tasks.rake +3 -1
  31. data/mensa.gemspec +1 -1
  32. metadata +11 -4
@@ -1,111 +1,109 @@
1
- .mensa-table {
2
- &__views {
3
- @apply relative flex-none;
4
-
5
- &__trigger {
6
- @apply h-full flex items-center gap-1.5 px-3 text-sm font-semibold text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 whitespace-nowrap cursor-pointer transition-colors;
7
- }
8
-
9
- &__trigger-icon {
10
- @apply text-gray-500 dark:text-gray-400 text-xs;
11
- }
12
-
13
- &__dropdown {
14
- @apply absolute left-0 top-full z-20 mt-1 min-w-[12rem] rounded-lg bg-white dark:bg-gray-800 shadow-lg ring-1 ring-black/5 dark:ring-white/10 py-1;
15
- }
16
-
17
- &__option {
18
- @apply flex items-center justify-between px-1 hover:bg-gray-50 dark:hover:bg-gray-700;
19
-
20
- &-btn {
21
- @apply flex items-center gap-2 flex-1 px-2 py-1.5 text-sm text-left text-gray-700 dark:text-gray-200 cursor-pointer;
22
- }
23
-
24
- &-check {
25
- @apply text-primary-600 text-xs w-4;
26
- }
27
-
28
- &-menu {
29
- @apply p-1.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 rounded cursor-pointer opacity-0 transition-opacity;
30
- }
31
-
32
- &:hover &-menu {
33
- @apply opacity-100;
34
- }
35
-
36
- &-system {
37
- @apply p-1.5 text-gray-400 opacity-0;
38
- }
39
-
40
- &:hover &-system {
41
- @apply p-1.5 text-gray-300 opacity-100;
42
- }
43
- }
44
-
45
- &__submenu {
46
- @apply absolute z-30 min-w-[11rem] rounded-lg bg-white dark:bg-gray-800 shadow-lg ring-1 ring-black/5 dark:ring-white/10 py-1;
47
-
48
- &-item {
49
- @apply flex items-center gap-2.5 w-full px-3 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer;
50
-
51
- i {
52
- @apply w-4 text-gray-400;
53
- }
54
-
55
- &--danger {
56
- @apply text-red-600 dark:text-red-400;
57
-
58
- i {
59
- @apply text-red-500;
60
- }
61
- }
62
- }
63
- }
64
-
65
- &__rename-dialog {
66
- @apply w-80 max-w-[90vw] rounded-xl border-0 p-5 bg-white dark:bg-gray-800 shadow-2xl ring-1 ring-black/5 dark:ring-white/10;
67
-
68
- &::backdrop {
69
- @apply bg-gray-900/40;
70
- backdrop-filter: blur(2px);
71
- }
72
- }
73
-
74
- &__rename-form {
75
- @apply flex flex-col gap-4;
76
- }
77
-
78
- &__rename-title {
79
- @apply text-base font-semibold text-gray-900 dark:text-gray-100;
80
- }
81
-
82
- &__rename-label {
83
- @apply flex flex-col gap-1.5 text-sm font-medium text-gray-700 dark:text-gray-300;
84
- }
85
-
86
- input&__rename-input {
87
- @apply w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm text-gray-900 dark:text-gray-100 shadow-sm placeholder:text-gray-400 focus:border-primary-500 focus:ring-2 focus:ring-primary-500 focus:outline-none;
88
- border-radius: 0.5rem;
89
- }
90
-
91
- &__rename-actions {
92
- @apply flex justify-end gap-2;
93
- }
94
-
95
- &__rename-btn {
96
- @apply rounded-lg px-3 py-1.5 text-sm font-semibold shadow-sm focus:outline-none transition-colors;
97
-
98
- &--secondary {
99
- @apply bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 ring-1 ring-inset ring-gray-300 dark:ring-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600;
100
- }
101
-
102
- &--primary {
103
- @apply bg-primary-600 text-white hover:bg-primary-500;
104
- }
105
- }
1
+ .mensa-table__views {
2
+ @apply relative flex-none;
3
+ }
4
+
5
+ .mensa-table__views__trigger {
6
+ @apply h-full flex items-center gap-1.5 px-3 text-sm font-semibold text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 whitespace-nowrap cursor-pointer transition-colors;
7
+ }
8
+
9
+ .mensa-table__views__trigger-icon {
10
+ @apply text-gray-500 dark:text-gray-400 text-xs;
11
+ }
12
+
13
+ .mensa-table__views__dropdown {
14
+ @apply absolute left-0 top-full z-20 mt-1 min-w-[12rem] rounded-lg bg-white dark:bg-gray-800 shadow-lg ring-1 ring-black/5 dark:ring-white/10 py-1;
15
+ }
16
+
17
+ .mensa-table__views__option {
18
+ @apply flex items-center justify-between px-1 hover:bg-gray-50 dark:hover:bg-gray-700;
19
+ }
20
+
21
+ .mensa-table__views__option-btn {
22
+ @apply flex items-center gap-2 flex-1 px-2 py-1.5 text-sm text-left text-gray-700 dark:text-gray-200 cursor-pointer;
23
+ }
24
+
25
+ .mensa-table__views__option-check {
26
+ @apply text-primary-600 text-xs w-4;
27
+ }
28
+
29
+ .mensa-table__views__option-menu {
30
+ @apply p-1.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 rounded cursor-pointer opacity-0 transition-opacity;
31
+ }
32
+
33
+ .mensa-table__views__option:hover .mensa-table__views__option-menu {
34
+ @apply opacity-100;
35
+ }
36
+
37
+ .mensa-table__views__option-system {
38
+ @apply p-1.5 text-gray-400 opacity-0;
39
+ }
40
+
41
+ .mensa-table__views__option:hover .mensa-table__views__option-system {
42
+ @apply p-1.5 text-gray-300 opacity-100;
43
+ }
44
+
45
+ .mensa-table__views__submenu {
46
+ @apply absolute z-30 min-w-[11rem] rounded-lg bg-white dark:bg-gray-800 shadow-lg ring-1 ring-black/5 dark:ring-white/10 py-1;
47
+ }
48
+
49
+ .mensa-table__views__submenu-item {
50
+ @apply flex items-center gap-2.5 w-full px-3 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer;
51
+
52
+ i {
53
+ @apply w-4 text-gray-400;
106
54
  }
107
55
  }
108
56
 
57
+ .mensa-table__views__submenu-item--danger {
58
+ @apply text-red-600 dark:text-red-400;
59
+
60
+ i {
61
+ @apply text-red-500;
62
+ }
63
+ }
64
+
65
+ .mensa-table__views__rename-dialog {
66
+ @apply w-80 max-w-[90vw] rounded-xl border-0 p-5 bg-white dark:bg-gray-800 shadow-2xl ring-1 ring-black/5 dark:ring-white/10;
67
+
68
+ &::backdrop {
69
+ @apply bg-gray-900/40;
70
+ backdrop-filter: blur(2px);
71
+ }
72
+ }
73
+
74
+ .mensa-table__views__rename-form {
75
+ @apply flex flex-col gap-4;
76
+ }
77
+
78
+ .mensa-table__views__rename-title {
79
+ @apply text-base font-semibold text-gray-900 dark:text-gray-100;
80
+ }
81
+
82
+ .mensa-table__views__rename-label {
83
+ @apply flex flex-col gap-1.5 text-sm font-medium text-gray-700 dark:text-gray-300;
84
+ }
85
+
86
+ input.mensa-table__views__rename-input {
87
+ @apply w-full rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 px-3 py-2 text-sm text-gray-900 dark:text-gray-100 shadow-sm placeholder:text-gray-400 focus:border-primary-500 focus:ring-2 focus:ring-primary-500 focus:outline-none;
88
+ border-radius: 0.5rem;
89
+ }
90
+
91
+ .mensa-table__views__rename-actions {
92
+ @apply flex justify-end gap-2;
93
+ }
94
+
95
+ .mensa-table__views__rename-btn {
96
+ @apply rounded-lg px-3 py-1.5 text-sm font-semibold shadow-sm focus:outline-none transition-colors;
97
+ }
98
+
99
+ .mensa-table__views__rename-btn--secondary {
100
+ @apply bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 ring-1 ring-inset ring-gray-300 dark:ring-gray-600 hover:bg-gray-50 dark:hover:bg-gray-600;
101
+ }
102
+
103
+ .mensa-table__views__rename-btn--primary {
104
+ @apply bg-primary-600 text-white hover:bg-primary-500;
105
+ }
106
+
109
107
  .tippy-box[data-theme~="mensa"] {
110
108
  @apply bg-gray-200 text-gray-800 dark:text-gray-400;
111
109
  }
@@ -6,6 +6,12 @@ export default class ApplicationController extends Controller {
6
6
  this.element[this.identifier] = this
7
7
  }
8
8
 
9
+ // Turbo streams re-render parts of the table via Mensa's own controllers, so the key
10
+ // rendered on the page's table element is the only stable one.
11
+ get tableStorageKey() {
12
+ return this.element.closest('.mensa-table')?.dataset.mensaTableStorageKeyValue
13
+ }
14
+
9
15
  // Appends a member id to a collection URL while keeping its query string
10
16
  // (e.g. the table's params[...]) intact.
11
17
  memberUrl(collectionUrl, id) {
@@ -145,6 +145,8 @@ module Mensa
145
145
  path = original_view_context.mensa.table_path(name)
146
146
  query = {
147
147
  params: user_params || params,
148
+ filters: filters_param,
149
+ query: current_query,
148
150
  order: order_hash(order),
149
151
  turbo_frame_id: turbo_frame_id,
150
152
  table_view_id: table_view_id,
@@ -165,9 +167,14 @@ module Mensa
165
167
  end
166
168
 
167
169
  # Key under which the browser persists this table's state (filters, order,
168
- # column order, ...). Tables built with different params get separate state.
170
+ # column order, ...), per controller, action and table.
169
171
  def storage_key
170
- [name, Mensa::TableParams.digest(params)].compact.join(":")
172
+ context = original_view_context if @original_view_context || component
173
+ if context.respond_to?(:controller_name) && context.respond_to?(:action_name)
174
+ "#{context.controller_name}_#{context.action_name}_#{name}"
175
+ else
176
+ name.to_s
177
+ end
171
178
  end
172
179
 
173
180
  def all_views
@@ -257,6 +264,13 @@ module Mensa
257
264
  current_aggregates.presence || ("" unless config[:aggregates].nil?)
258
265
  end
259
266
 
267
+ # Blank means "explicitly no filters", which overrides the view's default
268
+ def filters_param
269
+ return unless config.key?(:filters)
270
+
271
+ config[:filters].presence || ""
272
+ end
273
+
260
274
  private
261
275
 
262
276
  def ensure_internal_columns_for_joined_associations
@@ -7,6 +7,8 @@ module Mensa
7
7
  desc "Configures tailwind.config.js and application.tailwindcss.css"
8
8
 
9
9
  def add_content_to_tailwind_config
10
+ return unless File.exist?(File.join(destination_root, "config/tailwind.config.js"))
11
+
10
12
  inject_into_file "config/tailwind.config.js", before: "],\n theme: {" do
11
13
  " // Mensa content\n" +
12
14
  %w[/app/views/**/* /app/helpers/**/* /app/controllers/**/* /app/components/**/* /app/javascript/**/*.js /app/assets/**/*.css].map { |path| " \"#{Mensa::Engine.root}#{path}\"" }.join(",\n") +
@@ -15,6 +17,8 @@ module Mensa
15
17
  end
16
18
 
17
19
  def add_content_application_tailwind_css
20
+ return unless File.exist?(File.join(destination_root, "app/assets/stylesheets/application.tailwind.css"))
21
+
18
22
  inject_into_file "app/assets/stylesheets/application.tailwind.css", before: "@tailwind base;" do
19
23
  "@import '#{Mensa::Engine.root}/app/assets/stylesheets/mensa/application.css';\n"
20
24
  end
data/lib/mensa/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mensa
2
- VERSION = "0.8.0"
2
+ VERSION = "0.8.2"
3
3
  end
@@ -14,7 +14,9 @@ namespace :mensa do
14
14
  end
15
15
  end
16
16
 
17
- if Rake::Task.task_defined?("tailwindcss:build")
17
+ # tailwindcss-rails v4 picks up app/assets/tailwind/mensa/engine.css itself (via tailwindcss:engines),
18
+ # so only hook in the v3 config generator when that task is absent.
19
+ if Rake::Task.task_defined?("tailwindcss:build") && !Rake::Task.task_defined?("tailwindcss:engines")
18
20
  Rake::Task["tailwindcss:build"].enhance(["mensa:tailwindcss:config"])
19
21
  Rake::Task["tailwindcss:watch"].enhance(["mensa:tailwindcss:config"])
20
22
  end
data/mensa.gemspec CHANGED
@@ -37,7 +37,7 @@ Gem::Specification.new do |spec|
37
37
  spec.add_dependency "pg", ">= 1.6"
38
38
  spec.add_dependency "view_component", ">=3"
39
39
 
40
- spec.add_dependency "tailwindcss-rails", "~> 3.3"
40
+ spec.add_dependency "tailwindcss-rails", ">= 3.3", "< 5"
41
41
  spec.add_dependency "importmap-rails"
42
42
  spec.add_dependency "turbo-rails"
43
43
  spec.add_dependency "stimulus-rails"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mensa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom de Grunt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-10-15 00:00:00.000000000 Z
11
+ date: 2026-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -98,16 +98,22 @@ dependencies:
98
98
  name: tailwindcss-rails
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
103
  version: '3.3'
104
+ - - "<"
105
+ - !ruby/object:Gem::Version
106
+ version: '5'
104
107
  type: :runtime
105
108
  prerelease: false
106
109
  version_requirements: !ruby/object:Gem::Requirement
107
110
  requirements:
108
- - - "~>"
111
+ - - ">="
109
112
  - !ruby/object:Gem::Version
110
113
  version: '3.3'
114
+ - - "<"
115
+ - !ruby/object:Gem::Version
116
+ version: '5'
111
117
  - !ruby/object:Gem::Dependency
112
118
  name: importmap-rails
113
119
  requirement: !ruby/object:Gem::Requirement
@@ -182,6 +188,7 @@ files:
182
188
  - app/assets/config/mensa_manifest.js
183
189
  - app/assets/images/mensa/.keep
184
190
  - app/assets/stylesheets/mensa/application.css
191
+ - app/assets/tailwind/mensa/engine.css
185
192
  - app/components/mensa/add_filter/component.css
186
193
  - app/components/mensa/add_filter/component.html.erb
187
194
  - app/components/mensa/add_filter/component.rb