hibiki_rails 0.13.0 → 0.14.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/lib/generators/hibiki/rails/scaffold_controller/templates/phlex/shared/views/list.rb.tt +13 -9
- data/lib/generators/hibiki/rails/scaffold_controller/templates/shared/views/_list.html.erb.tt +17 -14
- data/lib/hibiki/rails/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6b163c0d20f8fcca4839e8cfcae98316cae9b8d01bd4f81eece18e02a9ae39be
|
|
4
|
+
data.tar.gz: bf61ca3db0cd1ad769a7f5ee931a06362124841e4d62ba0bd55856d892511b85
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 317d9a267de7853075cc35f089099f5f5fc89060afa2db3afd298d8b955f5dd441fdd90d1d2780be561280c6a9e514f827901112ede534a6dd82f06cf763e9a3
|
|
7
|
+
data.tar.gz: 2623fa07782f9d5264592c4bc3e977cb229967b1810f1b05c121bd16dbbc546335c420fd855751ae0dda71e6a148b648623a010344dbec21283f764f76d9f813
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,29 @@ The gem and the npm package are released in lockstep and share these version
|
|
|
4
4
|
numbers — `app/assets/javascripts/hibiki.js` is a single copy served both ways,
|
|
5
5
|
so importmap and bundler apps always resolve identical client code.
|
|
6
6
|
|
|
7
|
+
## 0.14.0 — 2026-09-07
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
**The infinite-scroll Load-more control has a degraded path.** Under
|
|
12
|
+
`--infinite-scroll` the scaffold emitted one button that answered both a
|
|
13
|
+
click and the `visible` sentinel event, and gave it no `fallback:` on
|
|
14
|
+
purpose: a sentinel that navigates on a dead socket would make scrolling
|
|
15
|
+
navigate. Without JavaScript the button rendered and did nothing. The control
|
|
16
|
+
is now two elements. The wrapper (`books_load_more`, the same id) is the
|
|
17
|
+
sentinel and carries only `visible`. A link inside it is the click path, with
|
|
18
|
+
`fallback: true` and a real href: the query already reads `?page=N` as a
|
|
19
|
+
growing window, so a degraded click shows every window up to N, and the
|
|
20
|
+
link's fragment lands on the last row the reader had already seen. The JS
|
|
21
|
+
client is unchanged.
|
|
22
|
+
|
|
23
|
+
- Both view layers. The Phlex component uses a bare `a`, so no `LinkTo`
|
|
24
|
+
include; `page_url` is now emitted in both pagination modes.
|
|
25
|
+
- Regenerating an app changes only `_list.html.erb` / `list.rb`. A system
|
|
26
|
+
test that clicked `#books_load_more button` now clicks the `a`.
|
|
27
|
+
- Docs: the fallback contract in [The JS client] gains the rule — never give
|
|
28
|
+
a `visible` control a `fallback:`; split it as the scaffold does.
|
|
29
|
+
|
|
7
30
|
## 0.13.0 — 2026-09-07
|
|
8
31
|
|
|
9
32
|
### Changed
|
data/lib/generators/hibiki/rails/scaffold_controller/templates/phlex/shared/views/list.rb.tt
CHANGED
|
@@ -61,10 +61,11 @@ class <%= view_class_name(:list) %> < Views::Base
|
|
|
61
61
|
pages = <%= query_class_name %>.page_numbers(page: @page, page_count: @page_count)
|
|
62
62
|
<%= render_call(:pagination, ["page: @page", "page_count: @page_count", "pages: pages", %(anchor: "##{list_dom_id}"), "id: id", "url: page_url"], indent: 4, shared: true) %>
|
|
63
63
|
end
|
|
64
|
+
<% end -%>
|
|
64
65
|
|
|
65
|
-
# Real
|
|
66
|
-
# re-renders them with url_params fresh, so the
|
|
67
|
-
# truthful as the live state moves.
|
|
66
|
+
# Real hrefs for the <%= infinite? ? "Load-more link" : "page links" %>, carrying the current query
|
|
67
|
+
# state — the channel re-renders them with url_params fresh, so the
|
|
68
|
+
# fallback URLs stay truthful as the live state moves.
|
|
68
69
|
def page_url
|
|
69
70
|
->(n) do
|
|
70
71
|
query = @url_params.except(:page)
|
|
@@ -72,19 +73,22 @@ class <%= view_class_name(:list) %> < Views::Base
|
|
|
72
73
|
<%= index_helper(type: :path) %>(**query)
|
|
73
74
|
end
|
|
74
75
|
end
|
|
75
|
-
<% end -%>
|
|
76
76
|
<% if infinite? -%>
|
|
77
77
|
|
|
78
|
-
# `visible` is a pseudo-event backed by an IntersectionObserver
|
|
79
|
-
#
|
|
80
|
-
#
|
|
78
|
+
# `visible` is a pseudo-event backed by an IntersectionObserver: the wrapper
|
|
79
|
+
# is the scroll sentinel, the link inside it is the click path and its href
|
|
80
|
+
# the fallback. A sentinel must never fall back — scrolling into view on a
|
|
81
|
+
# dead socket would navigate.
|
|
81
82
|
def load_more
|
|
82
|
-
div<%= arg_list(%(id: "#{load_more_dom_id}"), *css_args(:load_more_wrap)) %> do
|
|
83
|
-
|
|
83
|
+
div<%= arg_list(%(id: "#{load_more_dom_id}"), *css_args(:load_more_wrap), "**on(:go_to_page, event: :visible, with: { page: @page + 1 })", indent: 8) %> do
|
|
84
|
+
# The STRING "false", not the boolean — Phlex omits false-valued attributes.
|
|
85
|
+
a<%= arg_list("href: load_more_href", *css_args(:btn_wide), "data: { turbo: \"false\" }.merge(on(:go_to_page, with: { page: @page + 1 },\n#{' ' * 42}fallback: true)[:data])", indent: 8) %> do
|
|
84
86
|
plain "Load more"
|
|
85
87
|
span<%= arg_list(*css_args(:muted_inline)) %> { " · #{@remaining} remaining" }
|
|
86
88
|
end
|
|
87
89
|
end
|
|
88
90
|
end
|
|
91
|
+
|
|
92
|
+
def load_more_href = "#{page_url.(@page + 1)}#<%= row_dom_id_prefix %>_#{@<%= controller_file_name %>.last.id}"
|
|
89
93
|
<% end -%>
|
|
90
94
|
end
|
data/lib/generators/hibiki/rails/scaffold_controller/templates/shared/views/_list.html.erb.tt
CHANGED
|
@@ -3,16 +3,14 @@
|
|
|
3
3
|
<%%# locals: (<%= list_locals_signature %>) -%>
|
|
4
4
|
<%%# The island's re-rendered fragment. Its root id is the broadcast target —
|
|
5
5
|
deliberately not the island root, which carries the stream source. %>
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
truthful as the live state moves. %>
|
|
6
|
+
<%%# Real hrefs for the <%= infinite? ? "Load-more link" : "page links" %>, carrying the current query
|
|
7
|
+
state — the channel re-renders them with url_params fresh, so the
|
|
8
|
+
fallback URLs stay truthful as the live state moves. %>
|
|
10
9
|
<%% page_url = ->(n) do
|
|
11
10
|
query = url_params.except(:page)
|
|
12
11
|
query[:page] = n unless n == 1
|
|
13
12
|
<%= index_helper(type: :path) %>(**query)
|
|
14
13
|
end %>
|
|
15
|
-
<% end -%>
|
|
16
14
|
<div id="<%= list_dom_id %>"<%= css_attr(:list) %>>
|
|
17
15
|
<% if inline_create? -%>
|
|
18
16
|
<%%# The inline create form — only the channel ever renders it (the New
|
|
@@ -44,20 +42,25 @@
|
|
|
44
42
|
<%% end %>
|
|
45
43
|
|
|
46
44
|
<% if infinite? -%>
|
|
47
|
-
<%%# `visible` is a pseudo-event backed by an IntersectionObserver
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
<%%# `visible` is a pseudo-event backed by an IntersectionObserver: the wrapper
|
|
46
|
+
is the scroll sentinel, the link inside it is the click path and its href
|
|
47
|
+
the fallback. A sentinel must never fall back — scrolling into view on a
|
|
48
|
+
dead socket would navigate. %>
|
|
50
49
|
<%% if remaining.positive? %>
|
|
51
|
-
|
|
52
|
-
<%%= tag.button(type: "button",
|
|
50
|
+
<%%= tag.div(id: "<%= load_more_dom_id %>",
|
|
53
51
|
<% if css? -%>
|
|
54
|
-
|
|
52
|
+
class: "<%= css(:load_more_wrap) %>",
|
|
55
53
|
<% end -%>
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
**on(:go_to_page, event: :visible, with: { page: page + 1 })) do %>
|
|
55
|
+
<%%= link_to "#{page_url.(page + 1)}#<%= row_dom_id_prefix %>_#{<%= controller_file_name %>.last.id}",
|
|
56
|
+
<% if css? -%>
|
|
57
|
+
class: "<%= css(:btn_wide) %>",
|
|
58
|
+
<% end -%>
|
|
59
|
+
data: { turbo: false }.merge(on(:go_to_page, with: { page: page + 1 },
|
|
60
|
+
fallback: true)[:data]) do %>
|
|
58
61
|
Load more<span<%= css_attr(:muted_inline) %>> · <%%= remaining %> remaining</span>
|
|
59
62
|
<%% end %>
|
|
60
|
-
|
|
63
|
+
<%% end %>
|
|
61
64
|
<%% end %>
|
|
62
65
|
<% else -%>
|
|
63
66
|
<%%= render "shared/pagination", page: page, page_count: page_count, pages: pages,
|
data/lib/hibiki/rails/version.rb
CHANGED