pagy 7.0.11 → 8.6.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.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/apps/calendar.ru +745 -0
  3. data/apps/demo.ru +435 -0
  4. data/apps/rails.ru +212 -0
  5. data/apps/repro.ru +177 -0
  6. data/apps/tmp/calendar.sqlite3 +0 -0
  7. data/apps/tmp/calendar.sqlite3-shm +0 -0
  8. data/apps/tmp/calendar.sqlite3-wal +0 -0
  9. data/apps/tmp/local_secret.txt +1 -0
  10. data/apps/tmp/pagy-keyset.sqlite3 +0 -0
  11. data/apps/tmp/pagy-keyset.sqlite3-shm +0 -0
  12. data/apps/tmp/pagy-keyset.sqlite3-wal +0 -0
  13. data/bin/pagy +100 -0
  14. data/{lib/config → config}/pagy.rb +31 -73
  15. data/javascripts/pagy-module.js +100 -0
  16. data/javascripts/pagy.js +4 -0
  17. data/javascripts/pagy.min.js +4 -0
  18. data/javascripts/pagy.min.js.map +10 -0
  19. data/javascripts/pagy.mjs +100 -0
  20. data/lib/optimist.rb +1022 -0
  21. data/lib/pagy/backend.rb +8 -3
  22. data/lib/pagy/calendar/day.rb +4 -3
  23. data/lib/pagy/calendar/month.rb +4 -3
  24. data/lib/pagy/calendar/quarter.rb +4 -3
  25. data/lib/pagy/calendar/unit.rb +106 -0
  26. data/lib/pagy/calendar/week.rb +3 -3
  27. data/lib/pagy/calendar/year.rb +4 -3
  28. data/lib/pagy/calendar.rb +55 -99
  29. data/lib/pagy/console.rb +2 -2
  30. data/lib/pagy/countless.rb +15 -10
  31. data/lib/pagy/extras/arel.rb +1 -1
  32. data/lib/pagy/extras/array.rb +1 -1
  33. data/lib/pagy/extras/bootstrap.rb +52 -63
  34. data/lib/pagy/extras/bulma.rb +49 -64
  35. data/lib/pagy/extras/calendar.rb +35 -5
  36. data/lib/pagy/extras/countless.rb +2 -2
  37. data/lib/pagy/extras/foundation.rb +52 -62
  38. data/lib/pagy/extras/gearbox.rb +28 -27
  39. data/lib/pagy/extras/headers.rb +1 -1
  40. data/lib/pagy/extras/i18n.rb +1 -1
  41. data/lib/pagy/extras/items.rb +21 -18
  42. data/lib/pagy/extras/{frontend_helpers.rb → js_tools.rb} +9 -6
  43. data/lib/pagy/extras/jsonapi.rb +2 -2
  44. data/lib/pagy/extras/materialize.rb +56 -52
  45. data/lib/pagy/extras/metadata.rb +6 -2
  46. data/lib/pagy/extras/overflow.rb +5 -4
  47. data/lib/pagy/extras/pagy.rb +82 -0
  48. data/lib/pagy/extras/semantic.rb +50 -51
  49. data/lib/pagy/extras/size.rb +40 -0
  50. data/lib/pagy/extras/standalone.rb +2 -2
  51. data/lib/pagy/extras/trim.rb +12 -12
  52. data/lib/pagy/extras/uikit.rb +51 -50
  53. data/lib/pagy/frontend.rb +39 -53
  54. data/lib/pagy/url_helpers.rb +9 -10
  55. data/lib/pagy.rb +51 -82
  56. data/{lib/locales → locales}/ar.yml +10 -11
  57. data/{lib/locales → locales}/be.yml +5 -5
  58. data/{lib/locales → locales}/bg.yml +5 -5
  59. data/{lib/locales → locales}/bs.yml +5 -5
  60. data/locales/ca.yml +21 -0
  61. data/locales/ckb.yml +18 -0
  62. data/{lib/locales → locales}/cs.yml +5 -5
  63. data/locales/da.yml +21 -0
  64. data/{lib/locales → locales}/de.yml +5 -5
  65. data/{lib/locales → locales}/en.yml +5 -5
  66. data/{lib/locales → locales}/es.yml +3 -3
  67. data/{lib/locales → locales}/fr.yml +5 -5
  68. data/{lib/locales → locales}/hr.yml +5 -5
  69. data/{lib/locales → locales}/id.yml +5 -5
  70. data/{lib/locales → locales}/it.yml +5 -5
  71. data/{lib/locales → locales}/ja.yml +5 -5
  72. data/{lib/locales → locales}/km.yml +5 -5
  73. data/locales/ko.yml +17 -0
  74. data/{lib/locales → locales}/nb.yml +5 -5
  75. data/{lib/locales → locales}/nl.yml +5 -5
  76. data/{lib/locales → locales}/nn.yml +5 -5
  77. data/{lib/locales → locales}/pl.yml +5 -5
  78. data/{lib/locales → locales}/pt-BR.yml +3 -3
  79. data/{lib/locales → locales}/pt.yml +3 -3
  80. data/locales/ru.yml +25 -0
  81. data/{lib/locales → locales}/sr.yml +5 -5
  82. data/{lib/locales → locales}/sv-SE.yml +5 -5
  83. data/{lib/locales → locales}/sv.yml +5 -5
  84. data/{lib/locales → locales}/sw.yml +5 -5
  85. data/{lib/locales → locales}/ta.yml +5 -5
  86. data/{lib/locales → locales}/tr.yml +5 -5
  87. data/{lib/locales → locales}/uk.yml +5 -5
  88. data/locales/vi.yml +17 -0
  89. data/{lib/locales → locales}/zh-CN.yml +5 -5
  90. data/{lib/locales → locales}/zh-HK.yml +5 -5
  91. data/{lib/locales → locales}/zh-TW.yml +5 -5
  92. data/{lib/stylesheets → stylesheets}/pagy.css +19 -34
  93. data/{lib/stylesheets → stylesheets}/pagy.scss +17 -19
  94. data/stylesheets/pagy.tailwind.css +21 -0
  95. metadata +76 -53
  96. data/lib/javascripts/pagy-dev.js +0 -112
  97. data/lib/javascripts/pagy-module.js +0 -111
  98. data/lib/javascripts/pagy.js +0 -1
  99. data/lib/locales/ca.yml +0 -23
  100. data/lib/locales/ckb.yml +0 -18
  101. data/lib/locales/da.yml +0 -23
  102. data/lib/locales/ko.yml +0 -19
  103. data/lib/locales/ru.yml +0 -27
  104. data/lib/locales/vi.yml +0 -17
  105. data/lib/pagy/calendar/helper.rb +0 -65
  106. data/lib/pagy/extras/navs.rb +0 -51
  107. data/lib/pagy/extras/support.rb +0 -40
  108. data/lib/stylesheets/pagy.tailwind.scss +0 -24
  109. /data/{lib/javascripts/pagy-module.d.ts → javascripts/pagy.d.ts} +0 -0
@@ -12,42 +12,43 @@ class Pagy # :nodoc:
12
12
  def setup_items_var
13
13
  return super if !@vars[:gearbox_extra] || @vars[:items_extra]
14
14
 
15
- gearbox_items = @vars[:gearbox_items]
16
- raise VariableError.new(self, :gearbox_items, 'to be an Array of positives', gearbox_items) \
17
- unless gearbox_items.is_a?(Array) && gearbox_items.all? { |num| num.positive? rescue false } # rubocop:disable Style/RescueModifier
15
+ gears = @vars[:gearbox_items]
16
+ raise VariableError.new(self, :gearbox_items, 'to be an Array of positives', gears) \
17
+ unless gears.is_a?(Array) && gears.all? { |num| num.positive? rescue false } # rubocop:disable Style/RescueModifier
18
18
 
19
- @items = gearbox_items[@page - 1] || gearbox_items.last
19
+ @items = gears[@page - 1] || gears.last
20
20
  end
21
21
 
22
- # Setup @pages and @last based on the :gearbox_items variable (not used by Pagy::Countless)
23
- def setup_pages_var
22
+ # Setup @offset based on the :gearbox_items variable
23
+ def setup_offset_var
24
24
  return super if !@vars[:gearbox_extra] || @vars[:items_extra]
25
25
 
26
- gearbox_items = @vars[:gearbox_items]
27
- # This algorithm is thousands of times faster than the one in the geared_pagination gem
28
- @pages = @last = (if @count > (sum = gearbox_items.sum)
29
- [((@count - sum).to_f / gearbox_items.last).ceil, 1].max + gearbox_items.count
30
- else
31
- pages = 0
32
- remainder = @count
33
- while remainder.positive?
34
- pages += 1
35
- remainder -= gearbox_items[pages - 1]
36
- end
37
- [pages, 1].max
38
- end)
26
+ gears = @vars[:gearbox_items]
27
+ @offset = if @page <= gears.count
28
+ gears[0, @page - 1].sum
29
+ else
30
+ gears.sum + (gears.last * (@page - gears.count - 1))
31
+ end + @outset
39
32
  end
40
33
 
41
- # Setup @offset based on the :gearbox_items variable
42
- def setup_offset_var
34
+ # Setup Pagy @last based on the :gearbox_items variable and @count
35
+ def setup_last_var
43
36
  return super if !@vars[:gearbox_extra] || @vars[:items_extra]
44
37
 
45
- gearbox_items = @vars[:gearbox_items]
46
- @offset = if @page <= gearbox_items.count
47
- gearbox_items[0, @page - 1].sum
48
- else
49
- gearbox_items.sum + (gearbox_items.last * (@page - gearbox_items.count - 1))
50
- end + @outset
38
+ gears = @vars[:gearbox_items]
39
+ # This algorithm is thousands of times faster than the one in the geared_pagination gem
40
+ @last = (if count > (sum = gears.sum)
41
+ [((count - sum).to_f / gears.last).ceil, 1].max + gears.count
42
+ else
43
+ pages = 0
44
+ remainder = count
45
+ while remainder.positive?
46
+ pages += 1
47
+ remainder -= gears[pages - 1]
48
+ end
49
+ [pages, 1].max
50
+ end)
51
+ @last = vars[:max_pages] if vars[:max_pages] && @last > vars[:max_pages]
51
52
  end
52
53
  end
53
54
  prepend GearboxExtra
@@ -1,7 +1,7 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/headers
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/url_helpers'
4
+ require_relative '../url_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:headers] = { page: 'current-page',
@@ -19,7 +19,7 @@ class Pagy # :nodoc:
19
19
  end
20
20
  end
21
21
  end
22
- Calendar.prepend I18nExtra::CalendarOverride if defined?(Calendar)
22
+ Calendar::Unit.prepend I18nExtra::CalendarOverride if defined?(Calendar::Unit)
23
23
 
24
24
  # Add the pagy locales to the I18n.load_path
25
25
  ::I18n.load_path += Dir[Pagy.root.join('locales', '*.yml')]
@@ -1,7 +1,7 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/items
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/extras/frontend_helpers'
4
+ require_relative 'js_tools'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:items_param] = :items
@@ -33,27 +33,30 @@ class Pagy # :nodoc:
33
33
 
34
34
  # Additions for the Frontend module
35
35
  module FrontendAddOn
36
- ITEMS_PLACEHOLDER = '__pagy_items__'
36
+ ITEMS_TOKEN = '__pagy_items__'
37
37
 
38
38
  # Return the items selector HTML. For example "Show [20] items per page"
39
- def pagy_items_selector_js(pagy, pagy_id: nil, item_name: nil, item_i18n_key: nil)
39
+ def pagy_items_selector_js(pagy, id: nil, item_name: nil)
40
40
  return '' unless pagy.vars[:items_extra]
41
41
 
42
- p_id = %( id="#{pagy_id}") if pagy_id
43
- p_vars = pagy.vars
44
- p_items = p_vars[:items]
45
- p_vars[:items] = ITEMS_PLACEHOLDER
46
- url_token = pagy_url_for(pagy, PAGE_TOKEN)
47
- p_vars[:items] = p_items # restore the items
48
-
49
- html = +%(<span#{p_id} class="pagy pagy-items-selector-js" #{pagy_data(pagy, :selector, pagy.from, url_token)}>)
50
- input = %(<input name="items" type="number" min="1" max="#{p_vars[:max_items]}" value="#{
51
- p_items}" style="padding: 0; text-align: center; width: #{p_items.to_s.length + 1}rem;">)
52
- html << pagy_t('pagy.items_selector_js',
53
- item_name: item_name || pagy_t(item_i18n_key || p_vars[:item_i18n_key], count: p_items),
54
- items_input: input,
55
- count: p_items)
56
- html << %(</span>)
42
+ id = %( id="#{id}") if id
43
+ vars = pagy.vars
44
+ items = vars[:items]
45
+ vars[:items] = ITEMS_TOKEN
46
+ url_token = pagy_url_for(pagy, PAGE_TOKEN)
47
+ vars[:items] = items # restore the items
48
+
49
+ items_input = %(<input name="items" type="number" min="1" max="#{vars[:max_items]}" value="#{
50
+ items}" style="padding: 0; text-align: center; width: #{items.to_s.length + 1}rem;">#{JSTools::A_TAG})
51
+
52
+ %(<span#{id} class="pagy items-selector-js" #{
53
+ pagy_data(pagy, :selector, pagy.from, url_token)
54
+ }><label>#{
55
+ pagy_t('pagy.items_selector_js',
56
+ item_name: item_name || pagy_t('pagy.item_name', count: items),
57
+ items_input:,
58
+ count: items)
59
+ }</label></span>)
57
60
  end
58
61
  end
59
62
  Frontend.prepend ItemsExtra::FrontendAddOn
@@ -4,17 +4,20 @@ class Pagy # :nodoc:
4
4
  DEFAULT[:steps] = false # default false will use {0 => @vars[:size]}
5
5
 
6
6
  # Private module documented in the main classes
7
- module FrontendHelpers
7
+ module JSTools
8
+ # Dummy tag for input helpers: needed because Turbo does not intercept window.location changes
9
+ A_TAG = '<a href="#" style="display: none;">#</a>'
10
+
8
11
  # Additions for the Pagy class
9
12
  module PagyAddOn
10
13
  # `Pagy` instance method used by the `pagy*_nav_js` helpers.
11
14
  # It returns the sequels of width/series generated from the :steps hash
12
15
  # Example:
13
- # >> pagy = Pagy.new(count:1000, page: 20, steps: {0 => [1,2,2,1], 350 => [2,3,3,2], 550 => [3,4,4,3]})
16
+ # >> pagy = Pagy.new(count:1000, page: 20, steps: {0 => 5, 350 => 7, 550 => 9})
14
17
  # >> pagy.sequels
15
- # #=> { "0" => [1, :gap, 18, 19, "20", 21, 22, :gap, 50],
16
- # "350" => [1, 2, :gap, 17, 18, 19, "20", 21, 22, 23, :gap, 49, 50],
17
- # "550" => [1, 2, 3, :gap, 16, 17, 18, 19, "20", 21, 22, 23, 24, :gap, 48, 49, 50] }
18
+ # #=> { "0" => [18, 19, "20", 21, 22],
19
+ # "350" => [1, :gap, 19, "20", 21, :gap, 50],
20
+ # "550" => [1 :gap, 18, 19, "20", 21, 22, :gap, 50] }
18
21
  # Notice: if :steps is false it will use the single {0 => @vars[:size]} size
19
22
  def sequels(steps: @vars[:steps] || { 0 => @vars[:size] }, **_)
20
23
  raise VariableError.new(self, :steps, 'to define the 0 width', steps) unless steps.key?(0)
@@ -39,7 +42,7 @@ class Pagy # :nodoc:
39
42
  end
40
43
  end
41
44
  end
42
- Calendar.prepend CalendarOverride if defined?(Calendar)
45
+ Calendar::Unit.prepend CalendarOverride if defined?(Calendar::Unit)
43
46
 
44
47
  # Additions for the Frontend
45
48
  module FrontendAddOn
@@ -1,7 +1,7 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/jsonapi
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/url_helpers'
4
+ require_relative '../url_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:jsonapi] = true
@@ -42,7 +42,7 @@ class Pagy # :nodoc:
42
42
  return super if pagy_skip_jsonapi?(vars)
43
43
  return 1 if params[:page].nil?
44
44
 
45
- params[:page][vars[:page_param] || DEFAULT[:page_param]].to_i
45
+ [params[:page][vars[:page_param] || DEFAULT[:page_param]].to_i, 1].max
46
46
  end
47
47
  end
48
48
  Backend.prepend BackendOverride
@@ -1,25 +1,26 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/materialize
2
1
  # frozen_string_literal: true
3
2
 
4
- require 'pagy/extras/frontend_helpers'
3
+ warn '[PAGY WARNING] The materialize extra has been discontinued and it will be removed in v9 ' \
4
+ '(https://github.com/ddnexus/pagy/discussions/672#discussioncomment-9212328)'
5
+
6
+ require_relative 'js_tools'
5
7
 
6
8
  class Pagy # :nodoc:
7
9
  # Frontend modules are specially optimized for performance.
8
10
  # The resulting code may not look very elegant, but produces the best benchmarks
9
11
  module MaterializeExtra
10
12
  # Pagination for materialize: it returns the html with the series of links to the pages
11
- def pagy_materialize_nav(pagy, pagy_id: nil, link_extra: '',
12
- nav_aria_label: nil, nav_i18n_key: nil, **vars)
13
- p_id = %( id="#{pagy_id}") if pagy_id
14
- link = pagy_link_proc(pagy, link_extra:)
13
+ def pagy_materialize_nav(pagy, id: nil, aria_label: nil, **vars)
14
+ id = %( id="#{id}") if id
15
+ a = pagy_anchor(pagy)
15
16
 
16
- html = +%(<div#{p_id} class="pagy-materialize-nav pagination" role="navigation" #{
17
- nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)}><ul class="pagination">)
18
- html << materialize_prev_html(pagy, link)
17
+ html = +%(<div#{id} class="pagy-materialize nav pagination" role="navigation" #{
18
+ nav_aria_label(pagy, aria_label:)}><ul class="pagination">#{
19
+ materialize_prev_html(pagy, a)})
19
20
  pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
20
21
  html << case item
21
22
  when Integer
22
- %(<li class="waves-effect">#{link.call(item)}</li>)
23
+ %(<li class="waves-effect">#{a.(item)}</li>)
23
24
  when String
24
25
  %(<li class="active"><a role="link" aria-current="page" aria-disabled="true">#{pagy.label_for(item)}</a></li>)
25
26
  when :gap
@@ -28,67 +29,70 @@ class Pagy # :nodoc:
28
29
  raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
29
30
  end
30
31
  end
31
- html << materialize_next_html(pagy, link)
32
- html << %(</ul></div>)
32
+ html << %(#{materialize_next_html(pagy, a)}</ul></div>)
33
33
  end
34
34
 
35
- # Javascript pagination for materialize: it returns a nav and a JSON tag used by the pagy.js file
36
- def pagy_materialize_nav_js(pagy, pagy_id: nil, link_extra: '',
37
- nav_aria_label: nil, nav_i18n_key: nil, **vars)
35
+ # Javascript pagination for materialize: it returns a nav with a data-pagy attribute used by the pagy.js file
36
+ def pagy_materialize_nav_js(pagy, id: nil, aria_label: nil, **vars)
38
37
  sequels = pagy.sequels(**vars)
39
- p_id = %( id="#{pagy_id}") if pagy_id
40
- link = pagy_link_proc(pagy, link_extra:)
38
+ id = %( id="#{id}") if id
39
+ a = pagy_anchor(pagy)
41
40
 
42
- tags = { 'before' => %(<ul class="pagination">#{materialize_prev_html pagy, link}),
43
- 'link' => %(<li class="waves-effect">#{link.call(PAGE_TOKEN, LABEL_TOKEN)}</li>),
44
- 'active' => %(<li class="active"><a role="link" aria-current="page" aria-disabled="true">#{LABEL_TOKEN}</a></li>),
45
- 'gap' => %(<li class="gap disabled"><a role="link" aria-disabled="true">#{pagy_t 'pagy.gap'}</a></li>),
46
- 'after' => %(#{materialize_next_html pagy, link}</ul>) }
41
+ tokens = { 'before' => %(<ul class="pagination">#{materialize_prev_html pagy, a}),
42
+ 'a' => %(<li class="waves-effect">#{a.(PAGE_TOKEN, LABEL_TOKEN)}</li>),
43
+ 'current' => %(<li class="active"><a role="link" aria-current="page" aria-disabled="true">#{
44
+ LABEL_TOKEN}</a></li>),
45
+ 'gap' => %(<li class="gap disabled"><a role="link" aria-disabled="true">#{pagy_t 'pagy.gap'}</a></li>),
46
+ 'after' => %(#{materialize_next_html pagy, a}</ul>) }
47
47
 
48
- %(<div#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-materialize-nav-js" role="navigation" #{
49
- nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)} #{
50
- pagy_data(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></div>)
48
+ %(<div#{id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-materialize nav-js" role="navigation" #{
49
+ nav_aria_label(pagy, aria_label:)} #{
50
+ pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
51
+ }></div>)
51
52
  end
52
53
 
53
- # Javascript combo pagination for materialize: it returns a nav and a JSON tag used by the pagy.js file
54
- def pagy_materialize_combo_nav_js(pagy, pagy_id: nil, link_extra: '',
55
- nav_aria_label: nil, nav_i18n_key: nil)
56
- p_id = %( id="#{pagy_id}") if pagy_id
57
- link = pagy_link_proc(pagy, link_extra:)
58
- p_page = pagy.page
59
- p_pages = pagy.pages
60
- style = ' style="vertical-align: middle"'
61
- input = %(<input name="page" type="number" class="browser-default" min="1" max="#{p_pages}" value="#{
62
- p_page}" style="text-align: center; width: #{p_pages.to_s.length + 1}rem;" aria-current="page">)
54
+ # Javascript combo pagination for materialize: it returns a nav with a data-pagy attribute used by the pagy.js file
55
+ def pagy_materialize_combo_nav_js(pagy, id: nil, aria_label: nil)
56
+ id = %( id="#{id}") if id
57
+ a = pagy_anchor(pagy)
58
+ pages = pagy.pages
59
+
60
+ page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page" ) <<
61
+ %(style="text-align: center; width: #{pages.to_s.length + 1}rem; height: 1.5rem; font-size: 1.2rem; ) <<
62
+ %(border: none; border-radius: 2px; color: white; background-color: #ee6e73;" class="browser-default"> ) <<
63
+ JSTools::A_TAG
63
64
 
64
- html = %(<ul#{p_id} class="pagy-materialize-combo-nav-js pagination chip" role="navigation" #{
65
- nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)})
66
- %(#{html} style="padding-right: 0" #{
67
- pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))}>#{
68
- materialize_prev_html pagy, link, style}<li class="pagy-combo-input">#{
69
- pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages}</li>#{
70
- materialize_next_html pagy, link, style}</ul>)
65
+ %(<ul#{id} class="pagy-materialize combo-nav-js pagination" role="navigation" style="padding-right: 0;" #{
66
+ nav_aria_label(pagy, aria_label:)} #{
67
+ pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))
68
+ }>#{
69
+ materialize_prev_html(pagy, a)
70
+ }<li style="vertical-align: -webkit-baseline-middle;"><label style="font-size: 1.2rem;">#{
71
+ pagy_t('pagy.combo_nav_js', page_input:, pages:)
72
+ }</label></li>#{
73
+ materialize_next_html(pagy, a)
74
+ }</ul>)
71
75
  end
72
76
 
73
77
  private
74
78
 
75
- def materialize_prev_html(pagy, link, style = '')
79
+ def materialize_prev_html(pagy, a)
76
80
  if (p_prev = pagy.prev)
77
- %(<li class="waves-effect prev"#{style}>#{
78
- link.call(p_prev, '<i class="material-icons">chevron_left</i>', prev_aria_label_attr)}</li>)
81
+ %(<li class="waves-effect prev">#{
82
+ a.(p_prev, '<i class="material-icons">chevron_left</i>', aria_label: pagy_t('pagy.aria_label.prev'))}</li>)
79
83
  else
80
- %(<li class="prev disabled"#{style}><a role="link" aria-disabled="true" #{
81
- prev_aria_label_attr}><i class="material-icons">chevron_left</i></a></li>)
84
+ %(<li class="prev disabled"><a role="link" aria-disabled="true" aria-label="#{
85
+ pagy_t('pagy.aria_label.prev')}"><i class="material-icons">chevron_left</i></a></li>)
82
86
  end
83
87
  end
84
88
 
85
- def materialize_next_html(pagy, link, style = '')
89
+ def materialize_next_html(pagy, a)
86
90
  if (p_next = pagy.next)
87
- %(<li class="waves-effect next"#{style}>#{
88
- link.call(p_next, '<i class="material-icons">chevron_right</i>', next_aria_label_attr)}</li>)
91
+ %(<li class="waves-effect next">#{
92
+ a.(p_next, '<i class="material-icons">chevron_right</i>', aria_label: pagy_t('pagy.aria_label.next'))}</li>)
89
93
  else
90
- %(<li class="next disabled"#{style}><a role="link" aria-disabled="true" #{
91
- next_aria_label_attr}><i class="material-icons">chevron_right</i></a></li>)
94
+ %(<li class="next disabled"#><a role="link" aria-disabled="true" aria-label="#{
95
+ pagy_t('pagy.aria_label.next')}><i class="material-icons">chevron_right</i></a></li>)
92
96
  end
93
97
  end
94
98
  end
@@ -1,7 +1,7 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/metadata
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/url_helpers'
4
+ require_relative '../url_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:metadata] = %i[ scaffold_url first_url prev_url page_url next_url last_url
@@ -17,7 +17,11 @@ class Pagy # :nodoc:
17
17
  def pagy_metadata(pagy, absolute: nil)
18
18
  scaffold_url = pagy_url_for(pagy, PAGE_TOKEN, absolute:)
19
19
  {}.tap do |metadata|
20
- keys = defined?(Calendar) && pagy.is_a?(Calendar) ? pagy.vars[:metadata] - %i[count items] : pagy.vars[:metadata]
20
+ keys = if defined?(Calendar::Unit) && pagy.is_a?(Calendar::Unit)
21
+ pagy.vars[:metadata] - %i[count items]
22
+ else
23
+ pagy.vars[:metadata]
24
+ end
21
25
  keys.each do |key|
22
26
  metadata[key] = case key
23
27
  when :scaffold_url then scaffold_url
@@ -27,8 +27,9 @@ class Pagy # :nodoc:
27
27
  initialize vars.merge!(page: @last) # re-run with the last page
28
28
  @vars[:page] = requested_page # restore the requested page
29
29
  when :empty_page
30
- @offset = @items = @from = @to = 0 # vars relative to the actual page
31
- if defined?(Calendar) && is_a?(Calendar) # only for Calendar instances
30
+ @offset = @items = @in = @from = @to = 0 # vars relative to the actual page
31
+ if defined?(Calendar::Unit) \
32
+ && is_a?(Calendar::Unit) # only for Calendar::Units instances
32
33
  edge = @order == :asc ? @final : @initial # get the edge of the overflow side (neat, but any time would do)
33
34
  @from = @to = edge # set both to the edge utc time (a >=&&< query will get no records)
34
35
  end
@@ -51,7 +52,7 @@ class Pagy # :nodoc:
51
52
  end
52
53
  end
53
54
  Pagy.prepend PagyOverride
54
- Pagy::Calendar.prepend PagyOverride if defined?(Calendar)
55
+ Pagy::Calendar::Unit.prepend PagyOverride if defined?(Calendar::Unit)
55
56
 
56
57
  # Support for Pagy::Countless class
57
58
  module CountlessOverride
@@ -66,7 +67,7 @@ class Pagy # :nodoc:
66
67
  raise # same as without the extra
67
68
  when :empty_page
68
69
  @offset = @items = @from = @to = 0 # vars relative to the actual page
69
- @vars[:size] = [] # no page in the series
70
+ @vars[:size] = 0 # no page in the series
70
71
  self
71
72
  else
72
73
  raise VariableError.new(self, :overflow, 'to be in [:empty_page, :exception]', @vars[:overflow])
@@ -0,0 +1,82 @@
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/pagy
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'js_tools'
5
+
6
+ class Pagy # :nodoc:
7
+ # Frontend modules are specially optimized for performance.
8
+ # The resulting code may not look very elegant, but produces the best benchmarks
9
+ module PagyExtra
10
+ # pagy_nav is defined in the Frontend itself
11
+ # Javascript pagination: it returns a nav with a data-pagy attribute used by the pagy.js file
12
+ def pagy_nav_js(pagy, id: nil, aria_label: nil, **vars)
13
+ sequels = pagy.sequels(**vars)
14
+ id = %( id="#{id}") if id
15
+ a = pagy_anchor(pagy)
16
+ tokens = { 'before' => prev_a(pagy, a),
17
+ 'a' => a.(PAGE_TOKEN, LABEL_TOKEN),
18
+ 'current' => %(<a class="current" role="link" aria-current="page" aria-disabled="true">#{
19
+ LABEL_TOKEN}</a>),
20
+ 'gap' => %(<a class="gap" role="link" aria-disabled="true">#{pagy_t('pagy.gap')}</a>),
21
+ 'after' => next_a(pagy, a) }
22
+
23
+ %(<nav#{id} class="#{'pagy-rjs ' if sequels.size > 1}pagy nav-js" #{
24
+ nav_aria_label(pagy, aria_label:)} #{
25
+ pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
26
+ }></nav>)
27
+ end
28
+
29
+ # Javascript combo pagination: it returns a nav with a data-pagy attribute used by the pagy.js file
30
+ def pagy_combo_nav_js(pagy, id: nil, aria_label: nil)
31
+ id = %( id="#{id}") if id
32
+ a = pagy_anchor(pagy)
33
+ pages = pagy.pages
34
+
35
+ page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page" ) <<
36
+ %(style="text-align: center; width: #{pages.to_s.length + 1}rem; padding: 0;">#{JSTools::A_TAG})
37
+
38
+ %(<nav#{id} class="pagy combo-nav-js" #{
39
+ nav_aria_label(pagy, aria_label:)} #{
40
+ pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))}>#{
41
+ prev_a(pagy, a)
42
+ }<label>#{
43
+ pagy_t('pagy.combo_nav_js', page_input:, pages:)
44
+ }</label>#{
45
+ next_a(pagy, a)
46
+ }</nav>)
47
+ end
48
+
49
+ # Return the previous page URL string or nil
50
+ def pagy_prev_url(pagy, absolute: false)
51
+ pagy_url_for(pagy, pagy.prev, absolute:) if pagy.prev
52
+ end
53
+
54
+ # Return the next page URL string or nil
55
+ def pagy_next_url(pagy, absolute: false)
56
+ pagy_url_for(pagy, pagy.next, absolute:) if pagy.next
57
+ end
58
+
59
+ # Return the enabled/disabled previous page anchor tag
60
+ def pagy_prev_a(pagy, text: pagy_t('pagy.prev'), aria_label: pagy_t('pagy.aria_label.prev'))
61
+ a = pagy_anchor(pagy)
62
+ prev_a(pagy, a, text:, aria_label:)
63
+ end
64
+
65
+ # Return the enabled/disabled next page anchor tag
66
+ def pagy_next_a(pagy, text: pagy_t('pagy.next'), aria_label: pagy_t('pagy.aria_label.next'))
67
+ a = pagy_anchor(pagy)
68
+ next_a(pagy, a, text:, aria_label:)
69
+ end
70
+
71
+ # Conditionally return the previous page link tag
72
+ def pagy_prev_link(pagy, absolute: false)
73
+ %(<link href="#{pagy_url_for(pagy, pagy.prev, absolute:)}"/>) if pagy.prev
74
+ end
75
+
76
+ # Conditionally return the next page link tag
77
+ def pagy_next_link(pagy, absolute: false)
78
+ %(<link href="#{pagy_url_for(pagy, pagy.next, absolute:)}"/>) if pagy.next
79
+ end
80
+ end
81
+ Frontend.prepend PagyExtra
82
+ end