studio-engine 0.141.2 → 0.141.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e37b982954e7699c21010d1269c9f8bb50e3f4b900b580216ab2a61907000cbb
4
- data.tar.gz: 2288aaaee5f9f64ed85893a1ea3d5c6f2027316fc00e1da2ef1370e597037994
3
+ metadata.gz: ca078eb9a5dbe6acfd9979b40081b446fc4a74455e21b9b8417a595225a19b42
4
+ data.tar.gz: 15c40bf152b5e6a6cd0d8459a22e2a32543a86c2c0821573b10e669afc5da63f
5
5
  SHA512:
6
- metadata.gz: 9ba01f6b9d3ca61b788e4076c04e1e9699fa602214d026267cf82e0839ea4a2b89f93d66e2ec7b532475bbd32fb77481ae6d4680594ea075c6c0c189f19bcc20
7
- data.tar.gz: f6f06cecfe7ef957aef4b61ecc586f972b264f9e13e2ca7502154b947fdcbc9a63a3d138b8c3903bace7f4200be6046ec4dcc41b89d863c70e8e438d30d80e38
6
+ metadata.gz: 35b1aeb4b523008613f191d4782482464ecf8048b75a7175177c944e4e7f2e170da64ab0435470d442aa6d8be08f83a4cca5bfd0f4e30ee804820cec73e65d12
7
+ data.tar.gz: de8d944eac95a2f399bd328e2513b95145eb208ea8f38600d188ec6b1ad7069240d4fb4c12324b25b650e66d40d9c45225c1d7374b6f0e66266a523b567233fe
data/CHANGELOG.md CHANGED
@@ -4,6 +4,13 @@ The format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This pro
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.141.3 — 2026-11-09
8
+
9
+ ### Fixed
10
+
11
+ - **Engine migrations pass a host's omakase lint.** Hosts copy `db/migrate/*.rb` as `*.studio_engine.rb` and lint the copies as their own; four engine migrations used `["a"]` where rubocop-rails-omakase wants `[ "a" ]`, which turned moms-app's release static check red. The sources are fixed (whitespace only, no behavior change), and `test/lib/migrations_host_lint_test.rb` runs the omakase config over `db/migrate` so a lint-red migration cannot ship. A host that already copied a migration keeps its copy; a host that hand-fixed one keeps its fix.
12
+ - **The sticky table header's copy no longer draws over the pinned page header.** As a table scrolled out, the copy was pushed up by the table's bottom into the page header's band, and at the same z-index (`--z-sticky`) it painted over the title, because it is appended to `<body>` and wins the tie (Turf Monster `/contests`, My Contests). The copy now stays at the pinned stack's bottom edge and gets shorter as the table leaves, with the copied row moving up inside it, and it stacks at `--z-sticky - 2`, under the page header and the stuck section header. `StudioStickyTableHeaders.placement` now also returns `height` and `shift`; `top` is never above `edge`. No host change.
13
+
7
14
  ## 0.141.2 — 2026-11-09
8
15
 
9
16
  ### Fixed
data/Gemfile CHANGED
@@ -110,3 +110,14 @@ end
110
110
  group :development, :test do
111
111
  gem "importmap-rails", ">= 2.0"
112
112
  end
113
+
114
+ # rubocop-rails-omakase lints the engine's MIGRATIONS with the config a host
115
+ # runs. Hosts copy db/migrate/*.rb into their own tree as *.studio_engine.rb, so
116
+ # an engine migration is linted by every host that installs it; moms-app runs
117
+ # this exact omakase config, and a copied migration once turned its release
118
+ # static check red over `["a"]` vs `[ "a" ]`. test/lib/migrations_host_lint_test.rb
119
+ # runs it over db/migrate only. Not a runtime dependency, and not a whole-engine
120
+ # style rule: the rest of the engine keeps its own style.
121
+ group :development, :test do
122
+ gem "rubocop-rails-omakase", require: false
123
+ end
@@ -25,10 +25,14 @@
25
25
  display: none;
26
26
  overflow: hidden;
27
27
  pointer-events: none;
28
- /* --z-sticky: it fakes a sticky <thead>, so a side panel or a menu opened over
29
- the table still covers it. The old bare 45 sat between the panel and dropdown
30
- tiers for no recorded reason. */
31
- z-index: var(--z-sticky, 30);
28
+ /* TWO RUNGS UNDER --z-sticky: under the pinned page header (--z-sticky) and the
29
+ stuck section header (--z-sticky - 1), and still over --z-raised content. It
30
+ fakes a sticky <thead>, so a side panel or a menu opened over the table still
31
+ covers it. At --z-sticky itself it TIED the page header, and a tie goes to the
32
+ later element: this one is appended to <body>, so it painted over the title.
33
+ The script also never places it above the stack's bottom edge
34
+ (sticky_table_header.js, placement), so the rung is the second guard. */
35
+ z-index: calc(var(--z-sticky, 30) - 2);
32
36
  }
33
37
 
34
38
  .sticky-table-header-clone table {
@@ -57,11 +57,22 @@
57
57
  }
58
58
 
59
59
  // Where the clone goes for one table, as a pure function of what was measured:
60
- // shown once the real header has scrolled up to the edge, and pushed up by the
61
- // table's own bottom so it leaves with the table.
60
+ // shown once the real header has scrolled up to the edge, and gone once the
61
+ // table's own bottom has.
62
+ //
63
+ // IT NEVER RISES ABOVE THE EDGE. As the table leaves, the clone used to be
64
+ // pushed up by the table's bottom (top = tableBottom - cloneHeight), and that
65
+ // slid it into the pinned page header's band, where it painted over the title
66
+ // (Turf Monster /contests: CONTEST / STATUS / ENTRY over "Contests"). A glass
67
+ // header is translucent, so even a clone stacked under it would show through.
68
+ // Now the shell stays at the edge and gets SHORTER, `height` = what is left of
69
+ // the table below the edge, and the copied row moves up inside it by `shift`
70
+ // (zero or negative), so the row still leaves with the table, cut at the edge.
62
71
  function placement({ edge, headerTop, tableBottom, cloneHeight }) {
63
72
  const active = headerTop <= edge && tableBottom > edge;
64
- return { active, top: active ? Math.min(edge, tableBottom - cloneHeight) : null };
73
+ if (!active) return { active, top: null, height: null, shift: null };
74
+ const height = Math.min(cloneHeight, tableBottom - edge);
75
+ return { active, top: edge, height, shift: height - cloneHeight };
65
76
  }
66
77
 
67
78
  window.StudioStickyTableHeaders = { loaded: true, pinnedEdge, placement };
@@ -151,7 +162,7 @@
151
162
  const tableRect = this.table.getBoundingClientRect();
152
163
  const scrollerRect = this.scroller.getBoundingClientRect();
153
164
  const cloneHeight = headerRect.height || this.cloneShell.getBoundingClientRect().height;
154
- const { active, top } = placement({
165
+ const { active, top, height, shift } = placement({
155
166
  edge, headerTop: headerRect.top, tableBottom: tableRect.bottom, cloneHeight
156
167
  });
157
168
 
@@ -169,9 +180,9 @@
169
180
  this.cloneShell.style.left = `${scrollerRect.left}px`;
170
181
  this.cloneShell.style.top = `${top}px`;
171
182
  this.cloneShell.style.width = `${scrollerRect.width}px`;
172
- this.cloneShell.style.height = `${cloneHeight}px`;
183
+ this.cloneShell.style.height = `${height}px`;
173
184
  this.cloneTable.style.width = `${tableRect.width}px`;
174
- this.cloneTable.style.transform = `translateX(${translateX}px)`;
185
+ this.cloneTable.style.transform = `translate(${translateX}px, ${shift}px)`;
175
186
  this.table.setAttribute("data-sticky-table-active", "true");
176
187
  }
177
188
  }
@@ -58,7 +58,9 @@
58
58
  IT JOINS THE STACK WITH data-pin="page" AND POSITIONS OFF --pin-page-top, the
59
59
  bottom of everything above it. --pin-stack-bottom includes the row's own edge,
60
60
  so a row positioned off it would chase itself down the page. Anything below,
61
- such as the sticky table header's clone, sits under the row with no edit.
61
+ such as the sticky table header's clone, sits under the row: the clone starts
62
+ at the stack's bottom edge, never above it, and stacks two rungs under the
63
+ row's --z-sticky (studio/sticky_table_header.css).
62
64
 
63
65
  THE SENTINEL stays at the row's place in the flow, and the row's distance from
64
66
  it is what "stuck" means, on every kind of header. It is absolutely positioned,
@@ -21,7 +21,7 @@ class CreateStudioLinks < ActiveRecord::Migration[7.2]
21
21
  add_index :studio_links, :kind
22
22
  # Covers both "this owner's links" and "this owner's referral" lookups
23
23
  # (referral_for) via the leading columns.
24
- add_index :studio_links, [:linkable_type, :linkable_id, :kind],
24
+ add_index :studio_links, [ :linkable_type, :linkable_id, :kind ],
25
25
  name: "idx_studio_links_owner_kind"
26
26
  end
27
27
  end
@@ -23,8 +23,8 @@ class CreateStudioEnumerals < ActiveRecord::Migration[7.2]
23
23
  t.timestamps
24
24
  end
25
25
 
26
- add_index :studio_enumerals, [:category, :key], unique: true
27
- add_index :studio_enumerals, [:category, :position]
28
- add_index :studio_enumerals, [:category, :rank]
26
+ add_index :studio_enumerals, [ :category, :key ], unique: true
27
+ add_index :studio_enumerals, [ :category, :position ]
28
+ add_index :studio_enumerals, [ :category, :rank ]
29
29
  end
30
30
  end
@@ -6,8 +6,10 @@
6
6
  #
7
7
  # STYLE NOTE: reference migrations are written omakase-rubocop-compatible
8
8
  # (spaces inside array brackets) because the installed copy is linted by the
9
- # CONSUMER's rubocop, not this gem's — an engine-styled copy fails the
10
- # consumer's cert untouched (measured on the Industries adoption ship).
9
+ # CONSUMER's rubocop — an engine-styled copy fails the consumer's cert
10
+ # untouched (measured on the Industries adoption ship).
11
+ # test/lib/migrations_host_lint_test.rb runs that omakase config over
12
+ # db/migrate, so a lint-red migration fails here first.
11
13
  class CreateStudioKnowledgeDocs < ActiveRecord::Migration[7.2]
12
14
  def change
13
15
  create_table :studio_knowledge_docs do |t|
@@ -5,7 +5,8 @@
5
5
  #
6
6
  # STYLE NOTE: reference migrations are written omakase-rubocop-compatible
7
7
  # (spaces inside array brackets) because the installed copy is linted by the
8
- # CONSUMER's rubocop, not this gem's.
8
+ # CONSUMER's rubocop. test/lib/migrations_host_lint_test.rb runs that omakase
9
+ # config over db/migrate, so a lint-red migration fails here first.
9
10
  class CreateStudioKnowledgeExpectations < ActiveRecord::Migration[7.2]
10
11
  def change
11
12
  create_table :studio_knowledge_expectations do |t|
@@ -30,6 +30,6 @@ class CreateStudioConnections < ActiveRecord::Migration[7.2]
30
30
  t.timestamps
31
31
  end
32
32
 
33
- add_index :studio_connections, [:provider, :account_key], unique: true
33
+ add_index :studio_connections, [ :provider, :account_key ], unique: true
34
34
  end
35
35
  end
@@ -42,7 +42,7 @@ class RequireSlugsOnEngineTables < ActiveRecord::Migration[7.2]
42
42
  "studio_geo_settings" => "geo",
43
43
  "studio_site_identities" => "site-identity"
44
44
  }.freeze
45
- TABLES = (["error_logs"] + NAMED.keys).freeze
45
+ TABLES = ([ "error_logs" ] + NAMED.keys).freeze
46
46
 
47
47
  def up
48
48
  set_lock_timeout
@@ -111,7 +111,7 @@ class RequireSlugsOnEngineTables < ActiveRecord::Migration[7.2]
111
111
  end
112
112
 
113
113
  def unique_slug_index(table)
114
- slug_indexes = connection.indexes(table).select { |index| Array(index.columns) == ["slug"] }
114
+ slug_indexes = connection.indexes(table).select { |index| Array(index.columns) == [ "slug" ] }
115
115
  return if slug_indexes.any?(&:unique)
116
116
 
117
117
  slug_indexes.each { |index| remove_index table, name: index.name }
@@ -1,3 +1,3 @@
1
1
  module Studio
2
- VERSION = "0.141.2"
2
+ VERSION = "0.141.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: studio-engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.141.2
4
+ version: 0.141.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex McRitchie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-11-09 00:00:00.000000000 Z
11
+ date: 2026-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails