Fix assorted issues when reloading pages with morphing and the pagination system

This patches 2 problems in Turbo/idiomorph that are causing problems when reloading the pagination frames:

- No remove callback in idiomorph when removing a node that had been mapped.
- Regression introduced by https://github.com/hotwired/turbo/pull/1311, where it won't prevent the removal of frames with refresh=morph

I will upstream both patches, this is temporary.

https://fizzy.37signals.com/5986089/cards/2291
This commit is contained in:
Jorge Manrubia
2025-10-16 13:37:11 +02:00
parent 317731b821
commit 8c8dbe888e
8 changed files with 6088 additions and 8 deletions
+26
View File
@@ -0,0 +1,26 @@
@layer components {
.pagination-link {
display: block;
flex: 1;
min-block-size: 1.5rem;
pointer-events: none;
text-decoration: none;
&.pagination-link--active-when-observed {
block-size: 0;
min-block-size: 0;
font-size: 0;
line-height: 0;
overflow: hidden;
visibility: hidden;
height: 0px;
text-indent: -9999px;
}
&[aria-busy="true"] {
.spinner {
display: block;
}
}
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ module ColumnsHelper
"drag-and-drop-refresh": true,
controller: "frame",
action: "turbo:before-frame-render->frame#morphRender turbo:before-morph-element->frame#morphReload"
options[:refresh] = :morph if src.present?
turbo_frame_tag(id, src: src, data: data, **options, &block)
end
end
+5 -1
View File
@@ -5,13 +5,15 @@ module PaginationHelper
def link_to_next_page(namespace, page, activate_when_observed: false, label: default_pagination_label(activate_when_observed), data: {}, **attributes)
if page.before_last? && !params[:previous]
pagination_link(namespace, page.number + 1, label: label, activate_when_observed: activate_when_observed, data: data, class: "btn txt-small center-block center", **attributes)
attributes[:class] = class_names(attributes[:class], "btn txt-small center-block center": !activate_when_observed)
pagination_link(namespace, page.number + 1, label: label, activate_when_observed: activate_when_observed, data: data, **attributes)
end
end
def pagination_link(namespace, page_number, activate_when_observed: false, label: default_pagination_label(activate_when_observed), url_params: {}, data: {}, **attributes)
link_to label, url_for(params.permit!.to_h.merge(page: page_number, **url_params)),
"aria-label": "Load page #{page_number}",
id: "#{namespace}-pagination-link-#{page_number}",
class: class_names(attributes.delete(:class), "pagination-link", { "pagination-link--active-when-observed" => activate_when_observed }),
data: {
frame: pagination_frame_id_for(namespace, page_number),
@@ -62,9 +64,11 @@ module PaginationHelper
private
def pagination_list(name, tag_element: :div, paginate_on_scroll: false, **properties, &block)
classes = properties.delete(:class)
properties[:id] ||= "#{name}-pagination-list"
tag.public_send tag_element,
class: token_list(name, "display-contents", classes),
data: { controller: "pagination", pagination_paginate_on_intersection_value: paginate_on_scroll },
**properties,
&block
end
@@ -90,7 +90,6 @@ export default class extends Controller {
#replacePaginationLinkWithFrame(linkElement) {
const turboFrame = this.#buildTurboFrameFor(linkElement)
this.#insertTurboFrameAtPosition(linkElement, turboFrame)
linkElement.remove()
}
#buildTurboFrameFor(linkElement) {
@@ -7,18 +7,18 @@
} do %>
<svg viewBox="0 0 200 100">
<path id="top-half" fill="transparent" d="M 20,100 A 80,80 0 0,1 180,100"/>
<path id="<%= dom_id(card, "bubble-top-half") %>" fill="transparent" d="M 20,100 A 80,80 0 0,1 180,100"/>
<text text-anchor="middle" fill="currentColor">
<textPath href="#top-half" startOffset="50%" dominant-baseline="middle" data-bubble-target="top"></textPath>
<textPath href="#<%= dom_id(card, "bubble-top-half") %>" startOffset="50%" dominant-baseline="middle" data-bubble-target="top"></textPath>
</text>
</svg>
<span class="bubble__number" data-bubble-target="center"></span>
<svg viewBox="0 0 200 100">
<path id="bottom-half" d="M 20,0 A 80,80 0 0,0 180,0" fill="transparent"/>
<path id="<%= dom_id(card, "bubble-bottom-half") %>" d="M 20,0 A 80,80 0 0,0 180,0" fill="transparent"/>
<text text-anchor="middle" fill="currentColor">
<textPath href="#bottom-half" startOffset="50%" dominant-baseline="middle" data-bubble-target="bottom"></textPath>
<textPath href="#<%= dom_id(card, "bubble-bottom-half") %>" startOffset="50%" dominant-baseline="middle" data-bubble-target="bottom"></textPath>
</text>
</svg>
<% end %>
+1
View File
@@ -1,4 +1,5 @@
<%= tag.aside \
id: "filters-settings",
class: class_names("filters flex align-center gap-half justify-center center margin-block-end", { "filters--expanded": user_filtering.expanded? }),
data: {
controller: "toggle-class filter-settings",
+1 -1
View File
@@ -1,7 +1,7 @@
# Pin npm packages by running ./bin/importmap
pin "application"
pin "@hotwired/turbo-rails", to: "turbo.min.js"
pin "@hotwired/turbo-rails", to: "turbo.patched.js"
pin "@hotwired/stimulus", to: "stimulus.min.js"
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
pin "@rails/request.js", to: "@rails--request.js" # @0.0.11
+6050
View File
File diff suppressed because it is too large Load Diff